本实验通过两组实验来对比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,就可以调用到子类对应方法