首页 > 代码库 > C++学习笔记2--面向对象
C++学习笔记2--面向对象
类的声明格式:
【类的实现】
第一种方法是将类的成员都定义在类体内。
第二种方法,也可以将类体内的成员函数的实现放在类体外,但如果类成员定义在类体外,需要用到域运算符“::”,放在类体内和类体外的效果是一样的。
C++语言可以实现将函数的声明和函数的定义放在不同的文件,一般在头文件放入函数的声明,在实现文件放入函数的实现。可将类的定义放在头文件中,将类成员变量放在实现文件内。
【构造函数】
类的构造方法:
CPerson()是CPerson的默认构造方法,构造方法可以定义为带参的。
【复制构造函数】
复制构造函数就是函数的参数是一个已经初始化的类对象。
范例:
【析构函数】
构造函数主要用来在对象创建时,给对象中的一些数据成员赋值,主要目的就是来初始化对象。
析构函数的功能是用来释放一个对象的,在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。
【类成员】
public属性的成员对外可见,对内可见。
private属性的成员对外不可见,对内可见。
protected属性的成员对外不可见,对内可见,且对派生类是可见的。
在默认情况下,类成员的属性为private。
【内联成员函数】
类内(类内默认inline)声明:inline char* GetUsername() const;
类外直接定义:inline char* CUser::GetUsername() const {...}
【静态类成员】
静态类成员在类成员定义前使用static关键字标识。例如:
静态数据成员可以是当前类的类型,而其他数据成员只能是当前类的指针或引用类型。
例:
静态数据成员可以作为成员函数的默认参数。
静态成员函数的丁一部分写在类外时无需加static。
C++类中藏有this指针。
【嵌套类】
范例:在定义CList类时,在内部定义了一个嵌套类CNode。
上述代码在嵌套类CNode中定义了一个私有成员m_Tag,定义了一个公有成员m_Name,对于外围类CList来说,通常他不能访问嵌套类的私有成员,虽然嵌套类是在其内部定义的。但是,上述代码在定义CNode类时将CList类作为自己的友元类,这使得CList类能够访问CNode类的私有成员。
对于内部的嵌套类来说,只允许其在外围的类域中使用,在其他类域或者作用域中是不可见的。
可以采用下述方法调用:
CList::CNode node;
局部类:类的定义放置在函数中。
【友元】friend
友元类:
友元方法:
对于由原函数来说,不仅可以是类的成员函数,还可以是一个全局函数。
【命名空间】
命名空间的定义格式为:
引用空间成员的一般形式为是:
命名空间名称::成员;
例:定义命名空间
class 类名标识符 { [public:] [数据成员的声明] [成员函数的声明] [private:] [数据成员的声明] [成员函数的声明] [protected:] [数据成员的声明] [成员函数的声明] };
【类的实现】
第一种方法是将类的成员都定义在类体内。
第二种方法,也可以将类体内的成员函数的实现放在类体外,但如果类成员定义在类体外,需要用到域运算符“::”,放在类体内和类体外的效果是一样的。
C++语言可以实现将函数的声明和函数的定义放在不同的文件,一般在头文件放入函数的声明,在实现文件放入函数的实现。可将类的定义放在头文件中,将类成员变量放在实现文件内。
【构造函数】
类的构造方法:
class CPerson { public: CPerson(); int m_iIndex; int getIndex(); }; //构造函数 CPerson::CPerson() { m_iIndex = 10; }
CPerson()是CPerson的默认构造方法,构造方法可以定义为带参的。
【复制构造函数】
复制构造函数就是函数的参数是一个已经初始化的类对象。
范例:
#include <iostream> #include <cstring> using namespace std; class Person { public: Person(int _index, char *_name); //构造函数 Person(Person & copyPerson); //复制构造函数 int index; char name[30]; }; //构造函数 Person::Person(int _index, char *_name) { index = _index; strcpy(name, _name); } //复制构造函数 Person::Person(Person & copyPerson) { index = copyPerson.index; strcpy(name, copyPerson.name); } int main(int argc, char *argv[]) { Person p(1, "lasolmi"); Person q(p); cout << q.name << endl; return 0; }
【析构函数】
构造函数主要用来在对象创建时,给对象中的一些数据成员赋值,主要目的就是来初始化对象。
析构函数的功能是用来释放一个对象的,在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反。
CPerson::~CPerson() { delete[] m_pMessage; }
【类成员】
public属性的成员对外可见,对内可见。
private属性的成员对外不可见,对内可见。
protected属性的成员对外不可见,对内可见,且对派生类是可见的。
在默认情况下,类成员的属性为private。
【内联成员函数】
类内(类内默认inline)声明:inline char* GetUsername() const;
类外直接定义:inline char* CUser::GetUsername() const {...}
【静态类成员】
静态类成员在类成员定义前使用static关键字标识。例如:
class CBook { public: static unsigned int m_Price; }; 在定义静态数据成员时,通常需要在类体外部对静态成员进行初始化。例如: unsigned int CBook::m_Price = 10; 对于静态成员来说,不仅可以通过对象访问,还可以直接使用类名访问。例如: int main(int argc,char* argv[]) { CBook book; cout << CBook::m_Price << endl; //通过类名访问静态成员 cout << book.m_Price << endl; //通过对象访问静态成员 return 0; }
静态数据成员可以是当前类的类型,而其他数据成员只能是当前类的指针或引用类型。
例:
class CBook { public: static unsigned int m_Price; CBook m_book; //非法的定义,不允许在该类中定义所属类的对象 static CBook m_VCbook; //正确,静态数据成员允许定义类的所属类对象 CBook *m_pBook; //正确,允许定义类的所属类型的指针类型对象 }
静态数据成员可以作为成员函数的默认参数。
静态成员函数的丁一部分写在类外时无需加static。
C++类中藏有this指针。
【嵌套类】
范例:在定义CList类时,在内部定义了一个嵌套类CNode。
#include <iostream> #include <cstring> using namespace std; #define MAXLEN 128 class CList { public: class CNode { friend class CList; private: int m_Tag; public: char m_Name[MAXLEN]; }; public: CNode m_Node; void SetNodeName(const char *pchData) { if(pchData != NULL) { strcpy(m_Node.m_Name, pchData); } } void SetNodeTag(int tag) { m_Node.m_Tag = tag; } }; int main(int argc, char* argv[]) { CList c; c.SetNodeName("lasolmi"); cout << c.m_Node.m_Name << endl; return 0; }
上述代码在嵌套类CNode中定义了一个私有成员m_Tag,定义了一个公有成员m_Name,对于外围类CList来说,通常他不能访问嵌套类的私有成员,虽然嵌套类是在其内部定义的。但是,上述代码在定义CNode类时将CList类作为自己的友元类,这使得CList类能够访问CNode类的私有成员。
对于内部的嵌套类来说,只允许其在外围的类域中使用,在其他类域或者作用域中是不可见的。
可以采用下述方法调用:
CList::CNode node;
局部类:类的定义放置在函数中。
【友元】friend
友元类:
class B { public: friend class A; ... }
友元方法:
class B { friend void A::function(); ... };
对于由原函数来说,不仅可以是类的成员函数,还可以是一个全局函数。
class B { friend void function(); ... } void function() {...}
【命名空间】
命名空间的定义格式为:
namespace 名称 { 常量、变量、函数等对象的定义 }
引用空间成员的一般形式为是:
命名空间名称::成员;
例:定义命名空间
#include <iostream> using namespace std; namespace MyName1 { //定义命名空间 int iValue = http://www.mamicode.com/10;>
另一种引用命名空间中成员的方法:使用using namespace语句。一般形式为:using namespace 命名空间名称;如果使用using namespace语句,则在引用空间中的成员时直接使用就可以。
例:定义嵌套的命名空间。#include <iostream> using namespace std; namespace Output { void show() { cout << "Output's function!" << endl; } namespace MyName { void Demo() { cout << "MyName's function!" << endl; } } } int main(int argc, char* argv[]) { Output::show(); Output::MyName::Demo(); return 0; }
【继承】
类继承的形式如下:class 派生类名标识符:[继承方式] 基类名标识符 { [访问控制修饰符:] [成员声明列表] }
继承方式有3种派生类型:public,protected,private.
public(共有型派生):共有型派生表示对于基类中的public数据成员和成员函数,在派生类中仍然是public,对于基类中的private数据成员和成员函数,在派生类中仍然是private。
private(私有型派生):私有型派生表示对于基类中的public、protected数据成员和成员函数,在派生类中可以访问。基类中的private数据成员,在派生类中不可以访问。
protected(保护型派生):保护型派生表示对于基类中的public、protected数据成员和成员函数,在派生类中均为protected。protected类型在派生类定义时可以访问,用派生类声明的对象不可以访问,也就是说在类体外不可以访问。protected成员可以被基类的所有派生类使用。这一性质可以沿继承树无限向下传播。
【子类隐藏父类的成员函数】
设B类是A类的派生类,A中存在方法function(),B中也存在方法function(),则B类成员b使用自身function()方法为:
b.function();
子类使用父类function()方法为:
b.A::function();
【重载运算符】
重载运算符的声明形式:
operator 类型名();
不允许重载的运算符:“.”、“*”、“::”、“?”、“:”。
例:通过重载运算符实现求和#include <iostream> using namespace std; class CBook { public: CBook(int iPage) { m_iPage = iPage; } CBook operator+(CBook b) { return CBook(m_iPage+b.m_iPage); } void display() { cout << m_iPage <<endl; } protected: int m_iPage; }; int main(int argc,char* argv[]) { CBook bk1(10); CBook bk2(20); CBook tmp(0); tmp = bk1 + bk2; tmp.display(); return 0; }
【多重继承】
C++支持多重继承。多重继承是指有多个基类名标识符,其声明形式如下:class 派生类名标识符:[继承方式] 基类名标识符1,...,访问控制修饰符 基类名标识符n { [访问控制修饰符:] [成员声明列表] };
范例:鸟能够在天空飞翔,与能够在水里游,而水鸟既能够在天空飞翔,又能够在水里游。那么在定义水鸟类时,可以将鸟和鱼同时作为其基类。#include <iostream> using namespace std; class CBird { public: void FlyInSky() { cout << "鸟能够在天空飞翔" << endl; } void Breath() { cout << "鸟能够呼吸" << endl; } }; class CFish { public: void SwimInWater() { cout << "鱼能够在水里游" << endl; } void Breath() { cout << "鱼能够呼吸" << endl; } }; class CWaterBird: public CBird, public CFish { public: void Action() { cout << "水鸟能飞又能游" << endl; } }; int main(int argc, char* argv[]) { CWaterBird waterbird; waterbird.FlyInSky(); waterbird.SwimInWater(); return 0; }
当要用到Breath()方法,可以这么办:
waterbird.CFish::Breath(); //调用CFish类的Breath成员函数
waterbird.CBird::Breath(); //调用CBird类的Breath成员函er数
二义性:当派生类的两个或多个父类中都含有function函数,派生类将不知道调用哪个function成员函数,这就产生了二义性。
多重继承的构造函数被调用的顺序以类派生表中生命的顺序为准。派生表就是多重继承定义中继承方式后面的内容,调用顺序就是按照基类名标识符的前后顺序进行的。
【多态】
C++语言中,多态指:具有不同功能的函数可以用同一个函数名。
多态性通过联编实现。联编指计算机程序彼此关联的过程。
联编按进行的阶段不同分为:静态联编 和 动态联编。
C++中,按联编的时刻不同,存在两种类型多态性:函数重载 和 虚函数。
在基类中用virtual声明成员函数为虚函数。
覆盖和重载的区别是:重载是同一层次函数名相同,覆盖是在继承层次中成员函数的函数原型完全相同。
例:利用虚函数实现动态绑定#include <iostream> #include <cstring> using namespace std; class CEmployee { //定义CEmployee类 public: int m_ID; char m_Name[128]; char m_Depart[128]; CEmployee() { memset(m_Name, 0, 128); memset(m_Depart, 0, 128); } virtual void OutputName() { //定义一个虚成员函数 cout << "员工姓名:" << m_Name << endl; } }; class COperator:public CEmployee { //从CEmployee类派生一个子类 public: char m_Password[128]; void OutputName() { cout << "操作员姓名:" << m_Name << endl; } }; int main(int argc, char* argv[]) { CEmployee *pWorker = new COperator(); //定义CEmployee类型指针,调用COperator类构造函数 strcpy(pWorker->m_Name, "lasolmi"); //设置m_Name数据成员信息 pWorker->OutputName(); //调用COperator类的OutputName成员函数 delete pWorker; //释放对象 return 0; }
虚函数有以下几方面限制:
(1)只有类的成员函数才能为虚函数。
(2)静态成员函数不能为虚函数,因为静态成员函数不受限于某个对象。
(3)内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。
(4)构造函数不能使虚函数,析构函数通常是虚函数。
从CBird类和CFish类派生子类CWaterBird类时,在CWaterBird类中将存在两个CAnimal类的复制。那么如何在派生CWaterBird类时使其只存在一个CAnimal基类呢?C++语言提供的徐继承机制,解决了这个问题。
例:虚继承#include <iostream> using namespace std; class CAnimal { //定义一个动物类 public: CAnimal() {cout<<"动物类被构造"<<endl;} void move() {cout<<"动物能够移动"<<endl;} }; class CBird : virtual public CAnimal { //从CAnimal类虚继承CBird类 public: CBird() {cout<<"鸟类被构造"<<endl;} void FlyInSky() {cout<<"鸟能够在天空飞翔"<<endl;} void Breath() {cout<<"鸟能够呼吸"<<endl;} }; class CFish : virtual public CAnimal { //从CAnimal类虚继承CFish类 public: CFish() {cout<<"鱼类被构造"<<endl;} void SwimInWater() {cout<<"鱼能够在水里游"<<endl;} void Breath() {cout<<"与能够在水里游"<<endl;} }; class CWaterBird : public CBird,public CFish { public: CWaterBird() {cout<<"水鸟类被构造"<<endl;} void Action() {cout<<"水鸟既能飞又能游"<<endl;} }; int main(int argc,char* argv[]) { CWaterBird waterbird; return 0; }
输出结果为:
动物类被构造
鸟类被构造
鱼类被构造
水鸟类被构造
【抽象类】
包含至少一个纯虚函数的类称为抽象类。
抽象类只能作为基类用来派生出新的子类,而不能在程序中实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针。
纯虚函数(Pure Vitual Function):指被标明为不具体实现的虚成员函数,它不具备函数功能。
虚函数不能被直接调用,仅起到提供一个与派生类相一致的接口的作用。
声明虚函数的形式为:
virtual 类型 函数名(参数表列)=0;
实现抽象类中的成员函数:抽象类通常用于作为其他类的父类,从抽象类派生的子类如果是抽象类,则子类必须实现父类中的所有纯虚函数。
例:实现抽象类中的成员函数#include <iostream> #include <cstring> using namespace std; class CEmployee { //定义CEmployee类 public: int m_ID; char m_Name[128]; char m_Depart[128]; virtual void OutputName()=0; //定义抽象成员函数 }; class COperator : public CEmployee { public: char m_Password[128]; void OutputName() {cout<<"操作员姓名:"<<m_Name<<endl;} COperator() {strcpy(m_Name, "lasolmi");} }; class CSystemManager : public CEmployee { //定义CSystemManager类 public: char m_Password[128]; void OutputName() {cout<<"系统管理员姓名:"<<m_Name<<endl;} CSystemManager() {strcpy(m_Name, "congli");} }; int main(int argc, char* argv[]) { CEmployee *pWorker; //定义CEmployee类型指针 pWorker = new COperator(); //调用COperator类的构造函数,为pWorker赋值 pWorker->OutputName(); //调用COperator类的OutputName成员函数 delete pWorker; //释放pWorker对象 pWorker = NULL; //将pWorker对象设置为空 pWorker = new CSystemManager(); //调CSystemManager用类的构造函数,为pWorker赋值 pWorker->OutputName(); //调用CSystenManager类的OutputName成员函数 delete pWorker; //释放pWorker对象 pWorker = NULL; //将pWorker对象设置为空 return 0; }C++学习笔记2--面向对象
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。