C++ 类的学习(六) 虚函数
虚函数




类的指针


class CBox //基类
{
public:// 输出体积void showVolume() const{std::cout << "CBox usable volume is " << volume() << std::endl;}// 计算体积(虚函数)virtual double volume() const{return m_Length*m_Width*m_Height;}// 构造函数explicit CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0) :m_Length{ lv }, m_Width{ wv }, m_Height{ hv } {}protected:double m_Length;double m_Width;double m_Height;
};class CGlassBox : public CBox // 派生类
{
public:// 计算体积(override重写)virtual double volume() const override{return 0.85*m_Length*m_Width*m_Height;}// 构造函数CGlassBox(double lv, double wv, double hv) : CBox{ lv, wv, hv } {}
};int main()
{CBox myBox{ 2.0, 3.0, 4.0 }; // 实例化一定基类CGlassBox myGlassBox{ 2.0, 3.0, 4.0 }; // 实例化一个派生类CBox* pBox{}; // 基类指针pBox = &myBox; // 指针指向基类pBox->showVolume(); // 显示体积pBox = &myGlassBox; // 指针指向派生类pBox->showVolume(); // 显示体积return 0;
}
使用引用处理虚函数

class CBox //基类
{
public:// 输出体积void showVolume() const{std::cout << "CBox usable volume is " << volume() << std::endl;}// 计算体积(虚函数)virtual double volume() const{return m_Length*m_Width*m_Height;}// 构造函数explicit CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0) :m_Length{ lv }, m_Width{ wv }, m_Height{ hv } {}protected:double m_Length;double m_Width;double m_Height;
};class CGlassBox : public CBox // 派生类
{
public:// 计算体积(override重写)virtual double volume() const override{return 0.85*m_Length*m_Width*m_Height;}// 构造函数CGlassBox(double lv, double wv, double hv) : CBox{ lv, wv, hv } {}
};//形参为基类,传递派生类时,会选择派生类的虚函数
void output(const CBox& aBox)
{aBox.showVolume();
}int main()
{CBox myBox{ 2.0, 3.0, 4.0 }; // 实例化一个基类CGlassBox myGlassBox{ 2.0, 3.0, 4.0 }; // 实例化一个派生类output(myBox); // 输出基类output(myGlassBox); // 输出派生类return 0;
}纯虚函数


抽象类
抽象类不能实例化
可以使用抽象类的指针和引用

class CContainer
{
public: virtual double volume() const = 0;// =0表示纯虚函数// 输出体积virtual void showVolume() const{std::cout << "Volume is " << volume() << std::endl;}
};间接基类

虚析构函数
class CContainer // 抽象类
{
public://抽象类virtual double volume() const = 0;//虚函数virtual void showVolume() const{std::cout << "Volume is " << volume() << std::endl;}// virtual ~CContainer() // Comment out the next line and uncomment this for correct operation~CContainer(){std::cout << "CContainer destructor called" << std::endl;}
};class CCan : public CContainer
{
public://虚函数virtual double volume() const override{return 0.25*M_PI*m_Diameter*m_Diameter*m_Height;}// Constructorexplicit CCan(double hv = 4.0, double dv = 2.0) : m_Height{ hv }, m_Diameter{ dv } {}~CCan(){std::cout << "CCan destructor called" << std::endl;}protected:double m_Height;double m_Diameter;
};class CBox : public CContainer // Derived class
{
public://虚函数virtual void showVolume() const override{std::cout << "CBox usable volume is " << volume() << std::endl;}//虚函数virtual double volume() const override{return m_Length*m_Width*m_Height;}// Constructorexplicit CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):m_Length{ lv }, m_Width{ wv }, m_Height{ hv } {}~CBox(){std::cout << "CBox destructor called" << std::endl;}protected:double m_Length;double m_Width;double m_Height;
};class CGlassBox : public CBox // Derived class
{
public://虚函数virtual double volume() const override{return 0.85*m_Length*m_Width*m_Height;}~CGlassBox(){std::cout << "CGlassBox destructor called" << std::endl;}// ConstructorCGlassBox(double lv, double wv, double hv) : CBox{ lv, wv, hv } {}
};int main()
{CContainer* pC1{ new CBox{ 2.0, 3.0, 4.0 } }; //基类CCan myCan{ 6.5, 3.0 }; //直接派生类CGlassBox myGlassBox{ 2.0, 3.0, 4.0 }; //间接派生类pC1->showVolume(); // 输出基类体积delete pC1; // Now clean up the free storepC1 = new CGlassBox{ 4.0, 5.0, 6.0 }; // Create CGlassBox dynamicallypC1->showVolume(); // ...output its volume...std::cout << "Delete CGlassBox" << std::endl;delete pC1; // ...and delete itpC1 = &myCan; // 直接基类pC1->showVolume(); // Output the volume of CCanpC1 = &myGlassBox; //间接基类pC1->showVolume(); // Output the volume of CGlassBoxreturn 0;
}

