C++ 构造函数、析构函数调用虚函数

C++虚函数是通过虚表实现的,虚函数的地址记录在虚表中,只对象完成构造完成后,虚函数的地址才最终确定。

构造函数中调用虚函数

基类先于派生类构造,所以构造时没法调用到派生类的虚函数,也就是说只能调用到自己这一层,也就是虚函数失去多态功能。

析构函数调用虚函数

派生类先于基类析构,所以析构时基类没法调用到派生类的虚函数,同样只能调用到自己这一层,虚函数也失去多态功能。

代码

#include 

class Base
{
public:
    Base()
    {
        std::cout << "Base Construct.  ";
        this->fun2("Base::Base");
    }

    virtual ~Base()
    {
        std::cout << "Base Destruct.  ";
        this->fun2("Base::~Base");
    }

    virtual void fun()
    {
        std::cout << "Base::fun" << std::endl;
    }

    virtual void fun2(const char* caller)
    {
        std::cout << "Base::fun2, caller: " << caller << std::endl;
    }
};

class Derive : public Base
{
public:
    Derive()
    {
        std::cout << "Derive Construct.  ";
        this->fun2("Derive::Derive");
    }

    ~Derive() override
    {
        std::cout << "Derive Destruct.  ";
        this->fun2("Derive::~Derive");
    }

    void fun2(const char* caller) override
    {
        std::cout << "Derive::fun2: caller: " << caller << std::endl;
    }

    void fun() override
    {
        std::cout << "Derive::fun" << std::endl;
    }
};

int main()
{
    Base *p = new Derive;
    delete p;
    return 0;
}

运行结果:

Base Construct.  Base::fun2, caller: Base::Base
Derive Construct.  Derive::fun2: caller: Derive::Derive
Derive Destruct.  Derive::fun2: caller: Derive::~Derive
Base Destruct.  Base::fun2, caller: Base::~Base

在构造函数函数或者析构函数中调用虚函数,通常IDE会有警告,为了消除警告可以通过域名符号调用虚函数,此时相当于直接指定函数地址,不需要通过虚表所以不会有警告

class Base
{
public:
    Base()
    {
        std::cout << "Base Construct.  ";
        Base::fun2("Base::Base"); // 虚函数
    }

    virtual ~Base()
    {
        std::cout << "Base Destruct.  ";
        Base::fun2("Base::~Base"); // 虚函数
    }

    virtual void fun()
    {
        std::cout << "Base::fun" << std::endl;
    }

    virtual void fun2(const char* caller)
    {
        std::cout << "Base::fun2, caller: " << caller << std::endl;
    }
};

类函数指针

当类函数指针指向一个虚函数时,同样会触发多态,并不会直接调用函数指针对应的函数

#include 

class Base
{
public:
    virtual void fun()
    {
        std::cout << "Base::fun" << std::endl;
    }

};

class Derive : public Base
{
public:
    void fun() override
    {
        std::cout << "Derive::fun" << std::endl;
    }
};

int main()
{
    Base *p = new Derive;


    p->fun();
    p->Base::fun();
    auto pBFun = &Base::fun;
    auto pDFun = &Derive::fun;

    (p->*pBFun)();
    ((Derive*)p->*pDFun)();

    return 0;
}

结果

Derive::fun
Base::fun
Derive::fun
Derive::fun

你可能感兴趣的:(编程语言杂记,c++,开发语言)