重载继承的初始化
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;
}