类的声明格式:
【类的实现】
第一种方法是将类的成员都定义在类体内。
第二种方法,也可以将类体内的成员函数的实现放在类体外,但如果类成员定义在类体外,需要用到域运算符“::”,放在类体内和类体外的效果是一样的。
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
友元类:
友元方法:
对于由原函数来说,不仅可以是类的成员函数,还可以是一个全局函数。
【命名空间】
命名空间的定义格式为:
引用空间成员的一般形式为是:
命名空间名称::成员;
例:定义命名空间
另一种引用命名空间中成员的方法:使用using namespace语句。一般形式为:
例:定义嵌套的命名空间。
【继承】
类继承的形式如下:
继承方式有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 类型名();
不允许重载的运算符:“.”、“*”、“::”、“?”、“:”。
例:通过重载运算符实现求和
【多重继承】
C++支持多重继承。多重继承是指有多个基类名标识符,其声明形式如下:
范例:鸟能够在天空飞翔,与能够在水里游,而水鸟既能够在天空飞翔,又能够在水里游。那么在定义水鸟类时,可以将鸟和鱼同时作为其基类。
当要用到Breath()方法,可以这么办:
waterbird.CFish::Breath(); //调用CFish类的Breath成员函数
waterbird.CBird::Breath(); //调用CBird类的Breath成员函er数
二义性:当派生类的两个或多个父类中都含有function函数,派生类将不知道调用哪个function成员函数,这就产生了二义性。
多重继承的构造函数被调用的顺序以类派生表中生命的顺序为准。派生表就是多重继承定义中继承方式后面的内容,调用顺序就是按照基类名标识符的前后顺序进行的。
【多态】
C++语言中,多态指:具有不同功能的函数可以用同一个函数名。
多态性通过联编实现。联编指计算机程序彼此关联的过程。
联编按进行的阶段不同分为:静态联编 和 动态联编。
C++中,按联编的时刻不同,存在两种类型多态性:函数重载 和 虚函数。
在基类中用virtual声明成员函数为虚函数。
覆盖和重载的区别是:重载是同一层次函数名相同,覆盖是在继承层次中成员函数的函数原型完全相同。
例:利用虚函数实现动态绑定
虚函数有以下几方面限制:
(1)只有类的成员函数才能为虚函数。
(2)静态成员函数不能为虚函数,因为静态成员函数不受限于某个对象。
(3)内联函数不能是虚函数,因为内联函数是不能在运行中动态确定其位置的。
(4)构造函数不能使虚函数,析构函数通常是虚函数。
从CBird类和CFish类派生子类CWaterBird类时,在CWaterBird类中将存在两个CAnimal类的复制。那么如何在派生CWaterBird类时使其只存在一个CAnimal基类呢?C++语言提供的徐继承机制,解决了这个问题。
例:虚继承
输出结果为:
动物类被构造
鸟类被构造
鱼类被构造
水鸟类被构造
【抽象类】
包含至少一个纯虚函数的类称为抽象类。
抽象类只能作为基类用来派生出新的子类,而不能在程序中实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针。
纯虚函数(Pure Vitual Function):指被标明为不具体实现的虚成员函数,它不具备函数功能。
虚函数不能被直接调用,仅起到提供一个与派生类相一致的接口的作用。
声明虚函数的形式为:
virtual 类型 函数名(参数表列)=0;
实现抽象类中的成员函数:抽象类通常用于作为其他类的父类,从抽象类派生的子类如果是抽象类,则子类必须实现父类中的所有纯虚函数。
例:实现抽象类中的成员函数
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 = 10;
}
namespace MyName2 { //定义命名空间
int iValue = 20;
}
int iValue = 30; //全局变量
int main(int argc,char* argv[]) {
cout << MyName1::iValue << endl; //引用MyName1命名空间中的变量
cout << MyName2::iValue << endl; //引用MyName2命名空间中的变量
cout << iValue << endl;
return 0;
}
另一种引用命名空间中成员的方法:使用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;
}