c++虚函数和多态

楚天乐 3268 0 条

本实验通过两组实验来对比virtual对函数执行情况的影响。第一组实验用于验证virtual关键字对析构函数执行顺序的影响。第二组实验用于virtual关键字对一般函数执行的影响。

实验1:virtual析构函数

类结构:假设有基类A,A有派生类B1和B2,B2有派生类B3。
我们用三组实验来对照virtual关键字对析构函数执行的影响

  1. 基类A的析构函数~A不加virtual关键字,子类B1析构函数virtual,子类B2析构函数不加virtual
  2. 基类A的析构函数~Avirtual关键字,子类B1析构函数virtual,子类B2析构函数不加virtual,子类B3析构函数不加virtual
  3. 基类A的析构函数~Avirtual关键字,子类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的析构函数~Avirtual关键字,子类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的析构函数~Avirtual关键字,子类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函数执行的影响

  1. 基类A::print不加virtual关键字,子类B1::printvirtual,子类B2::print不加virtual
  2. 基类A::printvirtual关键字,子类B1::printvirtual,子类B2::print不加virtual

实验2.1

基类A::print不加virtual关键字,子类B1::printvirtual,子类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:printvirtual关键字,子类B1:printvirtual,子类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,就可以调用到子类对应方法



与本文相关的文章

发表我的评论
昵称 (必填)
邮箱 (必填)
网址
执行时间: 1714212841623.4 毫秒