【问题标题】:why is the base function called instead?为什么改为调用基本函数?
【发布时间】:2012-08-09 05:50:54
【问题描述】:

在下面code

#include <iostream>
using namespace std;

class A {
    public:
    A() {
        cout << " A constructor \n";
        sum(2,4);
    }
    virtual int sum(int a, int b){
        cout << "Base sum \n";
        return a + b;
    }
};

class B : public A {
    public:
    B() : A() {
        cout << " B constructor \n";
    }

    int sum(int a, int b){
        cout << "Overloaded sum \n";
        return (a + b) * 10;
    }
};

int main(){
    A* a = new B();
    // a->sum(4,5);
}

为什么即使我已将 A 的 sum 标记为虚拟并在 B 中重载它,也会调用它?在运行时,不应该在 vtable 的帮助下调用 B::sum() 吗?

【问题讨论】:

  • "overloaded" 不,你覆盖它!
  • 这里没有超载。

标签: c++ constructor virtual-functions vtable


【解决方案1】:

因为在您调用该方法时,a 还不是B 类型的对象。

避免从构造函数调用virtual 方法:它会导致意想不到的结果(当然,除非你期望这种确切的行为,在这种情况下你会发现)。

在运行时,不应该在 vtable 的帮助下调用 B::sum() 吗?

并非如此,因为该对象此时没有Bvtable

【讨论】:

  • 为了完整起见,类似的东西也适用于从析构函数进行此类调用。
  • 我很想学习。从构造函数调用虚方法有什么缺点(意外结果)? (除了调用虚函数并期望将调用派生函数)
  • @juanchopanza 你能详细说明一下吗?
  • @brainydexter 看到这个Scott Meyers link。基本上,当你到达基类析构函数时,派生对象实际上已经不存在了。
  • 啊哈是的!由于派生对象首先被销毁,然后是基础对象,因此当时没有派生对象。
【解决方案2】:

在实例化派生类时首先执行基构造函数。这意味着当基构造函数正在执行时,派生对象的构造还没有完成。

通过将构造函数中的操作限制为预期的方式来避免这些情况:初始化对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-29
    • 2011-09-16
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 2016-12-03
    相关资源
    最近更新 更多