基类:被其它类通过继承方式作为父类继承的类称为基类;描述派生类的统一种类的方式。
派生类:通过继承其他类(并可能含有自定义成员)实现的子类;为提高代码的重用性及与同样继承于同一个父类的其它类形成统一种类的方式。
虚基类:在一个子类同时继承了多个不同的父类时,而这些父类又同样继承了同一个父类,在没有声明虚基类时,这个顶层父类将会被实例化多个副本,多数情况我们不希望发生这样的事情,通过声明虚基类,可以避免顶层基类被实例化多个副本,这种方式称为虚基类。
虚析构:通过在析构函数前加上virtual来实现虚析构函数;当通过父类指针销毁子类的实例化对象时,虚析函数可有效的防止子类的析构无法被调用的情况。
虚函数:在函数声明的类型说明前含有virtual关键字的类成员函数;实现了多态性。
纯虚函数:类成员函数声明时函数体(包括花括号)被“=0”替代的没有函数实现的函数,其具有虚函数的所有特性,子类必须重写这个函数;防止子类在继承时没有重写指定函数而无法实现多态性。
抽象类:含有纯虚函数的类称为抽象类;抽象类只能作为基类,不能够被实例化。
// 这个示例说明了什么是基类、派生类及类的继承中发生的重载、重写对调用起到的影响,并且说明了怎样实现多态。
// virtualTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
class BaseClass
{
public:
void overLoad() { printf("BaseClass_overLoad\n"); }
virtual void overWrite() { printf("BaseClass_overWrite\n"); }
};
class A: public BaseClass
{
public:
void overLoad() { printf("派生类A_overLoad\n"); }
void overWrite() { printf("派生类A_overWrite\n"); }
};
class B: public BaseClass
{
public:
void overLoad() { printf("派生类B_overLoad\n"); }
void overWrite() { printf("派生类B_overWrite\n"); }
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
BaseClass* pBC[] = {&a, &b};
A* pA;
B* pB;
// 重载后的成员函数将随其调用者的类型而决定真正调用哪个函数
a.overLoad();
b.overLoad();
pBC[0]->overLoad();
pBC[1]->overLoad();
pA = (A*)pBC[0];
pB = (B*)pBC[0]; // 对类型A的实例做类型B的强转后其后调用发生了更加诡异的事
pA->overLoad(); // 这两句代码更能说明调用者本身对实际调用对象的决定作用
pB->overLoad();
printf("\n");
// 通过声明虚函数,重写后的成员函数实现了多态性,基类的指针将根据实际的实例类型而决定成员函数的调用
a.overWrite();
b.overWrite();
pBC[0]->overWrite();
pBC[1]->overWrite();
pA = (A*)pBC[0];
pB = (B*)pBC[0]; // 对类型A的实例做类型B的强转后将不再发生类型决定性的事
pA->overWrite(); // 这两句代码说明了多态性中调用者本身的类型已不再对实际调用对象起决定性作用
pB->overWrite();
printf("\n");
return 0;
}
// 下面这个示例将说明虚析构函数的作用
// virtualTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
class BaseClassA
{ public: virtual ~BaseClassA(void) { printf("BaseClassA_Destructor\n"); } };
class BaseClassB
{ public: ~BaseClassB(void) { printf("BaseClassB_Destructor\n"); } };
class A: public BaseClassA
{ public: ~A() { printf("派生类A_Destructor\n"); } };
class B: public BaseClassB
{ public: ~B() { printf("派生类B_Destructor\n"); } };
int _tmain(int argc, _TCHAR* argv[])
{
BaseClassA* pA = new A();
BaseClassB* pB = new B();
delete pA; // 析构过程安全
delete pB; // 因为父类没有声明虚析构函数,通过父类指针销毁子类示例化对象发生内存泄露
return 0;
}
// 下面这个示例将说明虚基类的作用
// virtualTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
class BaseClass
{ public: ~BaseClass(void) { printf("BaseClass_Destructor\n"); } };
class BaseClass1: virtual public BaseClass // 声明了虚基类继承关系
{ public: ~BaseClass1(void) { printf("BaseClass1_Destructor\n"); } };
class BaseClass2: virtual public BaseClass // 声明了虚基类继承关系
{ public: ~BaseClass2(void) { printf("BaseClass2_Destructor\n"); } };
class BaseClass3: public BaseClass // 没有声明虚基类继承关系
{ public: ~BaseClass3(void) { printf("BaseClass3_Destructor\n"); } };
class BaseClass4: public BaseClass // 没有声明虚基类继承关系
{ public: ~BaseClass4(void) { printf("BaseClass4_Destructor\n"); } };
class A: public BaseClass1, public BaseClass2
{ public: ~A() { printf("派生类A_Destructor\n"); } };
class B: public BaseClass3, public BaseClass4
{ public: ~B() { printf("派生类B_Destructor\n"); } };
class C: public BaseClass1, public BaseClass3
{ public: ~C() { printf("派生类C_Destructor\n"); } };
int _tmain(int argc, _TCHAR* argv[])
{
A a; // 继承了全部声明了虚基类的基类,顶层基类BaseClass只有一个副本
B b; // 继承了没有声明虚基类的基类,顶层基类BaseClass拥有两个副本
C c; // 继承了一个声明了虚基类的基类和一个没有声明虚基类的基类,顶层基类BaseClass仍然会出现两个副本
return 0;
}