【问题标题】:Virtual Function Signature Mismatch and its behavior虚函数签名不匹配及其行为
【发布时间】:2017-07-05 21:27:47
【问题描述】:

我正在看一个虚函数行为的示例。鉴于此测试代码,我对其行为有几个问题。

class A
{
public:
    A(int x)
    {
        cout << "In A Constructor" << endl;
        print();
    }
    ~A(){
        cout << "In A Destructor" << endl;
        delete _val;
    }
    virtual void print() { cout << "A." << endl; }
private:
    char* _val;
};

class B: public A
{
public:
    B(int x, int y) : A(x)
    {
        _dVal = new char[y];
        cout << "In B Constructor 1" << endl;
        print();
    }
    B() : A(0)
    {
        _dVal = new char[1];
        cout << "In B Constructor 2" << endl;
        print();
    }
    ~B(){
        cout << "In B Destructor" << endl;
        delete _dVal;
    }
    void print() { cout << "B" << endl; }
private:
    char* _dVal;
};

int main(int argc, char** argv) {
    A* p1 = new B();
    p1->print();
    delete p1;
    return 0;
}

输出是:

In A Constructor
A.
In B Constructor 2
B
B
In A Destructor

1) 如果类 A 是唯一一个将它表示为虚函数并且通过取消引用 (->) 调用的类 B,为什么要为类 B 调用 print? 2) 如果构造函数实际上被调用,为什么 B 的析构函数永远不会被调用?

【问题讨论】:

  • 如果函数在基类中是虚函数,那么它在所有派生类中也是虚函数。析构函数也是如此。
  • 每个问题一个问题。

标签: c++ constructor destructor virtual-functions


【解决方案1】:

1) 如果类 A 是唯一一个将它表示为虚函数并且通过取消引用 (->) 调用的类 B,为什么要为类 B 调用 print?

这就是虚函数应该做的。指针p1A* 类型,但实际上它指向的是B 类型的对象。并且这种动态绑定仅在使用指针或对基类的引用处理派生类时发生。

还要注意派生类中的覆盖函数也是virtual(无论在其声明中是否使用了关键字virtual)。

2) 如果构造函数实际上被调用,为什么 B 的析构函数永远不会被调用?

B 的析构函数未被调用,因为您没有将基类的析构函数(即A::~A)声明为virtual destructor。这种情况下的行为是未定义的。调用B 的构造函数是因为您通过new B() 显式构造了B

【讨论】:

  • 有趣。由于行为未定义,这是否意味着 B 类中的 _dVal 将成为 oprhan 并导致内存泄漏?
  • @user49096 从您观察到的结果来看,是的。请注意,它是不确定的,一切皆有可能。
  • @user49096 "既然行为是未定义的,那是否意味着" 不,这意味着发生的事情是未定义的、未定义的、未知的......
猜你喜欢
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
  • 2021-07-28
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多