类5-类的继承、虚函数、纯虚函数、虚析构函数
2011-09-15 17:04
357 查看
一、类的继承
就像家谱一样,就是一个继承图。爷爷-父亲-儿子-孙子等.类也一样,上面的类称为基类,也称父类。基类下面的类叫子类也叫派生类。
子类对父类的一些属性等有所继承也有所发展,因此才有了类的继承。
C++中类的继承格式为:
class ChildClass:public ParentClass;
子类后面要加上冒号及类限制符(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类为CChild的父类,我们此时声明Cparent指针p.因为是动态在自由存储区中分配的,而p又被声明为Cparent类型的指针,但在赋值时却指向子类。但在销毁时,系统认为它是cparent类型的,故会调用Cparent的析构函数,而子类的析构函数不会被执行。这就是我们用虚析构函数的原因。
因此:我们在类的继承时,总是把类的析构函数声明为虚析构函数是个好主意。
但构造函数是没有虚的,切记!
以下为代码:
Box.h
Box.cpp
ChildBox.h
ChildBox.cpp
main.cpp
本例中,我们把代码的头和定义分开了。
另因为CBox是抽象类,所以不能实例化它,故把main中的部分代码注释掉了,如果要把CBox类的中纯虚函数变成虚函数并实现它,则可以把注释的部分打开就可以编译。
就像家谱一样,就是一个继承图。爷爷-父亲-儿子-孙子等.类也一样,上面的类称为基类,也称父类。基类下面的类叫子类也叫派生类。
子类对父类的一些属性等有所继承也有所发展,因此才有了类的继承。
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类的中纯虚函数变成虚函数并实现它,则可以把注释的部分打开就可以编译。
相关文章推荐
- C++学习:虚函数,纯虚函数(virtual),虚继承,虚析构函数
- 171228—虚继承&虚基类、虚函数、纯虚函数&抽象类 这一家人
- 虚函数、纯虚函数与虚继承
- 虚函数、纯虚函数、虚基类、抽象类、虚函数继承、虚继承
- 关于继承中的 纯虚函数、虚函数和非虚函数的总结
- 虚函数、纯虚函数与非虚函数在继承方面的区别
- 虚函数,虚析构函数,纯虚函数,抽象类
- C++ 虚函数、纯虚函数、虚继承
- 抽象类、虚函数、纯虚函数、接口、多态、继承(多位置转载外加自己的一点代码)
- 静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数
- 虚函数、纯虚函数、虚基类、抽象类、虚函数继承、虚继承
- C++语言--多态性-8.1----多重继承、虚基类、虚函数和纯虚函数
- 纯虚函数、虚函数、虚析构函数
- 虚函数 纯虚函数 虚继承资料整理
- 【一天一篇CPP】多态性和虚函数和虚析构函数和纯虚函数和抽象类
- (1.1.10)虚函数、纯虚函数和虚继承的区别以及“覆盖”的概念
- 读书笔记--C++程序设计(第2版)--12多态性与虚函数(虚析构函数,纯虚函数与抽象类)
- 继承 、虚函数 、纯虚函数的区
- 虚函数继承、虚继承、虚析构函数、纯虚函数
- 虚函数,纯虚函数以及虚继承