赞
踩
class Base { public:Base(){} public: virtual void print(){cout<<"Base";} }; class Derived:public Base //base是基类(父类),Derived是派生类(子类) { public:Derived(){} public: void print(){cout<<"Derived";} }; int main() { Base *point=new Derived(); point->print(); }
输出:Derived
纯虚函数的定义如下:
C++语言为我们提供了一种语法结构,通过它可以指明,一个虚拟函数只是提供了一个可被子类型改写的接口。但是,它本身并不能通过虚拟机制被调用。这就是纯虚拟函数(purevirtual function)。纯虚拟函数的声明如下所示:
class Query {
public:
// 声明纯虚拟函数
virtual ostream& print( ostream&=cout ) const = 0;
// ...
};
这里函数声明后面紧跟赋值0。
包含一个或多个纯虚拟函数的类被编译器识别为抽象基类。抽象基类不能被实例化,一般用于继承。抽象基类只能作为子对象出现在后续的派生类中
【抽象类:C++ 接口(抽象类)】
虚继承:在继承定义中包含了virtual关键字的继承关系;
虚基类:在虚继承体系中的通过virtual继承而来的基类;
class A
{
void f1(){};
};
class B : public virtual A{
void f2(){};
};
在多继承下,虚继承就是为了解决菱形继承中,B,C都继承了A,D继承了B,C,那么D关于 A的引用只有一次,而不是 普通继承的 对于A引用了两次……
#include using namespace std; class Person{ public: Person(){ cout<<"Person构造"<<ENDL; } ~Person(){ cout<<"Person析构"<<ENDL; } }; class Teacher : virtual public Person{ public: Teacher(){ cout<<"Teacher构造"<<ENDL; } ~Teacher(){ out<<"Teacher析构"<<ENDL; } }; class Student : virtual public Person{ public: Student(){ cout<<"Student构造"<<ENDL; } ~Student(){ cout<<"Student析构"<<ENDL; } }; class TS : public Teacher, public Student{ public: TS(){ cout<<"TS构造"<<ENDL; } ~TS(){ cout<<"TS析构"<<ENDL; } }; int main(int argc,char* argv[]) { TS ts; return 0; }
这段代码的输出结果为:
Person构造
Teacher构造
Student构造
TS构造
TS析构
Student析构
Teacher析构
Person析构
当Teacher类和Student类没有虚继承Person类的时候,也就是把virtual去掉时候终端输出的结果为:
Person构造
Teacher构造
Person构造
Student构造
TS构造
TS析构
Student析构
Person析构
Teacher析构
Person析构
Teacher类和Student类没有虚继承Person类的结果不是我们所期望的。原因是Teacher类和Student类都继承于Person类。导致了构造TS的时候实例化了两个Person类。同样的道理,析构的时候也是析构了两次Person类。这是非常危险的,也就引发出了virtual的第三种用法,虚析构。
#include <iostream> using namespace std; class Person{ public: Person(){ cout<<"Person构造"<<endl; } virtual ~Person(){ cout<<"Person析构"<<endl; } }; class Teacher : public Person{ public: Teacher(){ cout<<"Teacher构造"<<endl; } ~Teacher(){ cout<<"Teacher析构"<<endl; } }; int main(int argc,char* argv[]) { Person *p= new Teacher; delete p; return 0; }
输出:
Person构造
Teacher构造
Teacher析构
Person析构
但是如果把上面语句 virtual ~Person(){ cout<<“Person析构”<<endl; }中的virtual去掉则代码运行结果会缺少Teacher析构。
虚析构总结一下就是:
(1)如果父类的析构函数不加virtual关键字
当父类的析构函数不声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,只调动父类的析构函数,而不调动子类的析构函数。
(2)如果父类的析构函数加virtual关键字
当父类的析构函数声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,先调动子类的析构函数,再调动父类的析构函数。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。