类5-类的继承、虚函数、纯虚函数、虚析构函数

一、类的继承

    就像家谱一样,就是一个继承图。爷爷-父亲-儿子-孙子等.类也一样,上面的类称为基类,也称父类。基类下面的类叫子类也叫派生类。

    子类对父类的一些属性等有所继承也有所发展,因此才有了类的继承。

     C++中类的继承格式为:

     class ChildClass:public ParentClass;

    子类后面要加上冒号及类限制符(public\protected\private)和基类。 

class CExample
{
public:
...
protected:
...
private:
...
}

在一个类中,会有三个访问限制符。

public 是公共,公开的意思,只要有对象访问CExample类,则它的public部分是可以被此对象访问的。

         如果是子类来继承的话,子类可以访问基本中这部分的信息。

protected 是保护的意思,即只有本类和子类可以访问这部分内容,其它的对象是不可以访问的。

private 是私有的,即只有本类可以访问这部分内容,其它的对象没有访问权限。

如果我们在继承基类的时候,如直接这样写:

  class CSample:CParent;

此时省略了限制访问类符号,系统默认是private级的,这时就会把基类中protected和public的成员全变成子类的private区内,基类的private 是不能访问的。

如果为protected,则只能访问父类中的protected及public,而public成员也在子类中变成protected属性.

如果为public,则父类中的protected也变成public。

记住以下三点:

   如果基类被声明为private,其成员在派生类中永远不可访问。

   如果基类被声明为protected, 其public成员在派生类中将成为protected.

   如果其类被声明为public,其在派生类中的访问级别保持不变。

二、类的虚函数

    什么叫虚函数?就是此函数已在父类中定义,但其在子类中可能要重新再定义。

    一般是在函数头前加上 virtual关键字。如 virtual type showinfo() const;

三、类的纯虚函数

    在基类中我们声明了一个函数成员,但没有给出具体实现,因为这个类只是一种很泛的抽象,具体实现函数的功能要在派生类中实现。它的格式为:

   virtual type showinfo() const=0;

  即在虚函数后面加上=0即可。

  这样的类也叫抽象类,抽象类不能实例化。

四、类的虚析构函数

    类的虚折构函数在动态产生对象后并用delete删除时有用,如果不是动态产生对象就不用做这样的声明。

   平常我们是静态编译的,在析构时,程序也是静态连接的,这时系统知道父类和子类之间的关系,就会先析构子类再析构父类。而在动态产生一个对象时,如下面的例子:

  Cparent* p=0;
p
=new CChild(100);
delete p;

在此类中,Cparent类为CChild的父类,我们此时声明Cparent指针p.因为是动态在自由存储区中分配的,而p又被声明为Cparent类型的指针,但在赋值时却指向子类。但在销毁时,系统认为它是cparent类型的,故会调用Cparent的析构函数,而子类的析构函数不会被执行。这就是我们用虚析构函数的原因。

因此:我们在类的继承时,总是把类的析构函数声明为虚析构函数是个好主意。

但构造函数是没有虚的,切记!

以下为代码:

  Box.h

#pragma once
class CBox
{
public:
CBox(
double lv,double wv, double hv);
CBox();
virtual double volume() const;
double getlength() const;

protected:
virtual void printclassInfo()=0;
double m_length;
double m_width;
double m_height;
};

Box.cpp

#include "Box.h"
#include
<iostream>
using namespace std;
CBox::CBox(
double lv,double wv,double hv):m_length(lv),m_width(wv),m_height(hv)
{
printf(
"Constructor Called!\n");
}
CBox::CBox()
{
printf(
"Default construct!\n");
}
double CBox::volume() const
{
return m_height*m_width*m_length;
}

double CBox::getlength() const
{
return m_length;
}

ChildBox.h

#pragma once
#include
"Box.h"

class CChildBox:public CBox
{
public:
CChildBox(
double lv,double wv,double hv);
double volume() const;
virtual void printclassInfo();
};

ChildBox.cpp

#include "ChildBox.h"
#include
<iostream>
using namespace std;

CChildBox::CChildBox(
double lv,double wv,double hv):CBox()
{
m_length
=lv;
m_width
=wv;
m_height
=hv;
printf(
"CChildBox Construct Called!\n");
}

double CChildBox::volume() const
{
return 3*3*3;

}

void CChildBox::printclassInfo()
{
printf(
"CChildBox\n");
}

main.cpp

#include "ChildBox.h"
#include
<iostream>
using namespace std;

void output(CBox& abox)
{
cout
<<endl
<<abox.volume()<<endl;
}
void main()
{
CChildBox childbox(
12,22,33);
//CBox box(3,0.3,3.5);

CBox
* p=0;
p
=&childbox;
printf(
"The volume is: %0.2f \n",p->volume());
printf(
"the getlength is: %0.2f\n",p->getlength());
output(childbox);
childbox.printclassInfo();
/*p=&box;
printf("The volume is: %0.2f \n",p->volume());
output(box);
*/
}

本例中,我们把代码的头和定义分开了。

另因为CBox是抽象类,所以不能实例化它,故把main中的部分代码注释掉了,如果要把CBox类的中纯虚函数变成虚函数并实现它,则可以把注释的部分打开就可以编译。

原文地址:https://www.cnblogs.com/yagzh2000/p/2177779.html