本实验通过两组实验来对比virtual对函数执行情况的影响。第一组实验用于验证virtual关键字对析构函数执行顺序的影响。第二组实验用于virtual关键字对一般函数执行的影响。
实验1:virtual析构函数
类结构:假设有基类A,A有派生类B1和B2,B2有派生类B3。
我们用三组实验来对照virtual关键字对析构函数执行的影响
- 基类A的析构函数~A不加virtual关键字,子类B1析构函数加virtual,子类B2析构函数不加virtual
- 基类A的析构函数~A加virtual关键字,子类B1析构函数加virtual,子类B2析构函数不加virtual,子类B3析构函数不加virtual
- 基类A的析构函数~A加virtual关键字,子类B1析构函数加virtual,子类B2析构函数加virtual
实验1.1
基类A的析构函数~A不加virtual关键字,子类B1析构函数加virtual,子类B2析构函数不加virtual
#include <iostream>
using namespace std;
class A{
public:
    ~A();
};
A::~A(){
    cout<<"destruct A"<<endl;
}
class B1 : public A{
public:
    virtual ~B1();
};
B1::~B1(){
    cout<<"destruct B1"<<endl;
}
class B2 : public A{
public:
    ~B2();
};
B2::~B2(){
    cout<<"destruct B2"<<endl;
}
int main()
{
    A *pa = new A();
    A *pb1 = new B1();
    A *pb2 = new B2();
    cout<<"\n析构pa\n======"<<endl;
    delete pa;
    cout<<"\n析构pb1\n======"<<endl;
    delete pb1;
    cout<<"\n析构pb2\n======"<<endl;
    delete pb2;
   return 0;
}输出
析构pa
======
destruct A
析构pb1
======
destruct A
析构pb2
======
destruct A
实验结果:如果父类析构函数没有标未virtual,无论子类析构函数有咩有virtual,子类的析构函数都不会执行
实验1.2
基类A的析构函数~A加virtual关键字,子类B1析构函数加virtual,子类B2析构函数不加virtual,子类B3析构函数不加virtual
#include <iostream>
using namespace std;
class A{
public:
    virtual ~A();
};
A::~A(){
    cout<<"destruct A"<<endl;
}
class B1 : public A{
public:
    virtual ~B1();
};
B1::~B1(){
    cout<<"destruct B1"<<endl;
}
class B2 : public A{
public:
    ~B2();
};
B2::~B2(){
    cout<<"destruct B2"<<endl;
}
class B3 : public B2{
public:
    ~B3();
};
B3::~B3(){
    cout<<"destruct B3"<<endl;
}
int main()
{
    A *pa = new A();
    A *pb1 = new B1();
    A *pb2 = new B2();
    A *pb3 = new B3();
    cout<<"\n析构pa\n======"<<endl;
    delete pa;
    cout<<"\n析构pb1\n======"<<endl;
    delete pb1;
    cout<<"\n析构pb2\n======"<<endl;
    delete pb2;
    cout<<"\n析构pb3\n======"<<endl;
    delete pb3;
   return 0;
}输出:
析构pa
======
destruct A
析构pb1
======
destruct B1
destruct A
析构pb2
======
destruct B2
destruct A
析构pb3
======
destruct B3
destruct B2
destruct A实验结果: 只要几类的析构函数标记为virtual,所有子类无论有没有virtual,都会在自己析构函数执行完成后执行父类析构函数
实验1.3
基类A的析构函数~A加virtual关键字,子类B1析构函数加virtual,子类B2析构函数加virtual
#include <iostream>
using namespace std;
class A{
public:
    virtual ~A();
};
A::~A(){
    cout<<"destruct A"<<endl;
}
class B1 : public A{
public:
    virtual ~B1();
};
B1::~B1(){
    cout<<"destruct B1"<<endl;
}
class B2 : public A{
public:
    virtual ~B2();
};
B2::~B2(){
    cout<<"destruct B2"<<endl;
}
int main()
{
    A *pa = new A();
    A *pb1 = new B1();
    A *pb2 = new B2();
    cout<<"\n析构pa\n======"<<endl;
    delete pa;
    cout<<"\n析构pb1\n======"<<endl;
    delete pb1;
    cout<<"\n析构pb2\n======"<<endl;
    delete pb2;
   return 0;
}输出结果
析构pa
======
destruct A
析构pb1
======
destruct B1
destruct A
析构pb2
======
destruct B2
destruct A实验结果:子类析构函数首先被调用,其次父类构造函数被调用
实验2, virtual print函数
类结构:假设有基类A,A有派生类B1和B2,B2有派生类B3。都有print方法.
我们用2组实验来对照virtual关键字对print函数执行的影响
- 基类A::print不加virtual关键字,子类B1::print加virtual,子类B2::print不加virtual
- 基类A::print加virtual关键字,子类B1::print加virtual,子类B2::print不加virtual
实验2.1
基类A::print不加virtual关键字,子类B1::print加virtual,子类B2::print不加virtual
#include <iostream>
using namespace std;
class A{
public:
    void print();
};
void A::print(){
    cout<<"A"<<endl;
}
class B1 : public A{
public:
    virtual void print();
};
void B1::print(){
    cout<<"BBB:111"<<endl;
}
class B2 : public A{
public:
    void print();
};
void B2::print(){
    cout<<"BBB:222"<<endl;
}
int main()
{
    A *pa = new A();
    A *pb1 = new B1();
    A *pb2 = new B2();
    pa->print();
    pb1->print();
    pb2->print();
    delete pa;
    delete pb1;
    delete pb2;
   return 0;
}输出:
A
A
A结论:父类方法没有virtual,无法调用到子类对应方法
实验2.2
基类A:print加virtual关键字,子类B1:print加virtual,子类B2:print不加virtual
#include <iostream>
using namespace std;
class A{
public:
    virtual void print();
};
void A::print(){
    cout<<"A"<<endl;
}
class B1 : public A{
public:
    virtual void print();
};
void B1::print(){
    cout<<"BBB:111"<<endl;
}
class B2 : public A{
public:
    void print();
};
void B2::print(){
    cout<<"BBB:222"<<endl;
}
int main()
{
    A *pa = new A();
    A *pb1 = new B1();
    A *pb2 = new B2();
    pa->print();
    pb1->print();
    pb2->print();
    delete pa;
    delete pb1;
    delete pb2;
   return 0;
}输出
A
BBB:111
BBB:222结论:只要父类方法有virtual,就可以调用到子类对应方法