c++继承机制(1)
(1) 我们先讨论这种线性继承机制:A->B->C->D 即B类继承了A,C继承了B,D继承了C;
测试代码如下:
#include<iostream>
using namespace std;
class A
{
public:
A() {cout<<"A construction"<<endl;}
~A()
{
cout<<"A destructor"<<endl;
}
};
class B: public A
{
public:
B() {cout<<"B construction"<<endl;}
~B()
{
cout<<"B destructor"<<endl;
}
};
class C: public B
{
public:
C() {cout<<"C construction"<<endl;}
~C()
{
cout<<"C destructor"<<endl;
}
};
class D:public C
{
public:
D(){ cout<<"D construction"<<endl;}
~D()
{
cout<<"D destructor"<<endl;
}
};
int main()
{
{
D d;
}
cout<<endl;
{
C c;
}
cout<<endl;
A* ptrA=new D();
delete ptrA;
return 0;
}
代码编译后运行结果如下:
我们可以看出,构造类D的实例或C的实例时,对构造函数的调用是从最底层基类开始构造。即:A-B-C-D或A-B-C。对析构函数的调用与构造函数的调用顺序恰恰相反。 即D-C-B-A或C-B-A。
当我们定义一个基类指针指向派生类对象时,在线性继承条件下,构造函数的调用顺序同样是从基类到派生类。但是当我们试图去释放基类指针所指对象的内存块时,仅仅是调用了基类A的析构函数。而B、C、D所分配的内存空间并没有释放,将造成内存泄漏。我们希望的是调用类D的析构函数,这样所有内存空间将会被释放。解决方法就是给作为基类的析构函数设置为虚函数即可,这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。一般情况下我们将作为基类的析构函数设成虚函数 。对于A* ptrA=new D(),我们只需要把A类的析构函数设置为虚函数即可,此时B、C、D的析构函数默认为虚析构函数。 对于B* ptrB=new D(),我们只需要把B设置为虚析构函数即可。
(2) 多重继承:派生类多次继承同一个基类。即B、C都继承于A,D继承B、C。默认情况下,派生类中含有继承链上每个类对应的子部分。如果某基类在派生链中出现多次,则该派生类中将包含该类的多个子对象。
测试代码如下:
#include<iostream>
using namespace std;
class A
{
public:
A() {cout<<"A construction"<<endl;}
virtual~A()
{
cout<<"A destructor"<<endl;
}
};
class B: public A
{
public:
B() {cout<<"B construction"<<endl;}
~B()
{
cout<<"B destructor"<<endl;
}
};
class C: public A
{
public:
C() {cout<<"C construction"<<endl;}
~C()
{
cout<<"C destructor"<<endl;
}
};
class D:public C,public B
{
public:
D(){ cout<<"D construction"<<endl;}
~D()
{
cout<<"D destructor"<<endl;
}
};
int main()
{
cout<<sizeof(D)<<endl;
{
D d;
}
cout<<endl;
{
C c;
}
cout<<endl;
A* ptrA=new D();
delete ptrA;
return 0;
}
代码编译后运行结果如下:
造成这样问题的原因是因为从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,解决方法是将共同基类设置为虚基类。盗图如下:
实现如下:
#include<iostream>
using namespace std;
class A
{
public:
A() {cout<<"A construction"<<endl;}
virtual~A()
{
cout<<"A destructor"<<endl;
}
};
class B: virtual public A
{
public:
B() {cout<<"B construction"<<endl;}
~B()
{
cout<<"B destructor"<<endl;
}
};
class C: virtual public A
{
public:
C() {cout<<"C construction"<<endl;}
~C()
{
cout<<"C destructor"<<endl;
}
};
class D:public C,public B
{
public:
D(){ cout<<"D construction"<<endl;}
~D()
{
cout<<"D destructor"<<endl;
}
};
int main()
{
cout<<sizeof(D)<<endl;
{
D d;
}
cout<<endl;
{
C c;
}
cout<<endl;
A* ptrA=new D();
delete ptrA;
return 0;
}
运行效果: