C++多重继承、纯虚函数和抽象类

时间:2021-04-20 19:48:07

重载继承的初始化

1)如果类A和类B都同时继承自类X,类C继承自A和B,那么在创建类C的时候,类X的构造和析构函数

会被执行两次,因为类C在创建的时候,分别会去创建类A和类B,而类A和类B又会去创建类X,所以

就类X会被创建两次

2)如果类X中有函数Fun,那么类C在调用的时候需要指定调用哪个父类所继承的Fun函数,例如:c->A::Fun()

class X
{
public:
X(){}
virtual ~X(){}
virtual void Fun()
{
cout<<"Class X"<<endl;
}
};
class A:public X
{
public:
A(int i):a(i){}
virtual ~A(){}
virtual void print()
{
cout<<"Class A - "<<a<<endl;
}
private:
int a;
};

class B:public X
{
public:
B(int i):a(i){}
virtual ~B(){}
virtual void print()
{
cout<<"Class B - "<<a<<endl;
}
private:
int a;
};

class C:public A, public B
{
public:
//基类A和B的构造函数都是带参的,所以子类需要对其初始化,顺序随意
C(int i, int j, int k):A(i),B(j),a(k){}
virtual ~C(){}
virtual void print()
{
cout<<"Class C - "<<a<<endl;
}
private:
int a;
};

int main()
{
C *c = new C(1,2,3);
//如果多个基类中拥有相同的函数名,需要用::作用域标识符指出调用哪一个基类的函数,避免二义性
c->A::print();
c->B::print();
c->print();
//如果类A和类B都同时继承自类X,那么在创建类C的时候,类X的构造和析构函数会被执行两次,因为
//类C在创建的时候,分别会去创建类A和类B,而类A和类B又会去创建类X,所以就类X会被创建销毁两次
//如果类X中有函数Fun,那么类C在调用的时候需要指定调用哪个父类所继承的Fun函数
c->A::Fun();
//c->B::Fun();
delete c;
return 0;
}

再谈虚基类 前往以前的笔记

虚基类可以避免多重继承时函数调用的二义性,同理,也可以避免最上层的基类(这里指类X)被创建销毁两次

class X
{
public:
X(){cout<<"X构造函数"<<endl;}
virtual ~X(){cout<<"X析构函数"<<endl;}
virtual void Fun()
{
cout<<"Class X"<<endl;
}
};

//说明类X为虚基类
class A:virtual public X
{
public:
A(int i):a(i){cout<<"A构造函数"<<endl;}
virtual ~A(){cout<<"A析构函数"<<endl;}
private:
int a;
};

class B:virtual public X
{
public:
B(int i):a(i){cout<<"B构造函数"<<endl;}
virtual ~B(){cout<<"B析构函数"<<endl;}
private:
int a;
};

class C:public A, public B
{
public:
//基类A和B的构造函数都是带参的,所以子类需要对其初始化,顺序随意
//因为类X被限定只为子类产生一个实例,所以这里也可以对类X进行初始化
C(int i, int j, int k):/*X(...),*/A(i),B(j),a(k){cout<<"C构造函数"<<endl;}
virtual ~C(){cout<<"C析构函数"<<endl;}
private:
int a;
};

int main()
{
//类X只会被创建销毁一次,
C *c = new C(1,2,3);
//虚基类可以避免继承中的函数二义性
c->Fun();
delete c;
return 0;
}

纯虚函数和抽象类

将一个虚函数初始化为0,这个函数就变成了纯虚函数,例如:

virtual int fun() = 0;

这种函数没有任何具体功能,不能直接调用它,有纯虚函数的类是抽象的,所以也不能实例化

一个类如果继承了抽象类,那么这个类就必须实现该抽象类中的方法

如果这个子类没有全部覆盖抽象基类的方法,那么这个子类也会变成一个抽象类

class X
{
public:
virtual void print() = 0;
};
class A:public X
{
public:
A(){}
~A(){}
//类A必须实现抽象类里面的纯虚函数
void print(){cout<<"Class A"<<endl;}
//或者继续把这个函数设为虚函数,那此时类A也属于抽象类
//void print() = 0;
};
int main()
{
A *pA = new A();
pA->print();
return 0;
}