【问题标题】:Linker error from not declaring abstract method in abstract base class?未在抽象基类中声明抽象方法导致链接器错误?
【发布时间】:2013-05-10 13:49:01
【问题描述】:

我有一个抽象基类Foo 和一个名为bar 的抽象方法。 我从Foo 的构造函数中调用bar。我希望子类覆盖bar(毕竟它是抽象的),然后Foo 在每个实例上调用覆盖的bar:

class Foo
{
    public:
        Foo() { bar(); }
        virtual void bar() = 0;
}

但是,我收到一个错误:

foo.obj:-1: error: LNK2019: unresolved external symbol "protected: virtual void __cdecl Foo::bar(void)" (?bar@Foo@@MEAAXXZ) referenced in function "public: __cdecl Foo::Foo(void)" (??0Foo@@QEAA@XZ)

这种链接器错误通常意味着我已经定义了一些东西但没有声明它(或相反),这似乎又是这种情况。 如果我像这样为bar 添加定义,一切都会正常工作:

void Foo::bar() {}

这是预期的错误,还是链接器中的错误? 如果是故意的,为什么会这样? 我不明白为什么我不能从构造函数中调用抽象方法? 我想到的唯一原因是在定义子类方法之前调用了基类的构造函数,但我仍然认为我不应该得到这个错误?

我正在使用Qt Creator 2.7.0 - Based on Qt 5.0.2 (32 bit)

【问题讨论】:

    标签: c++ constructor abstract-class linker-errors abstract


    【解决方案1】:

    您的问题很简单,但也很困难:Foo 的构造函数在派生类的构造函数之前运行。因此,虚函数设置为 Foo 设置的任何值 - 未实现。

    您必须等到构建完成才能按您期望的方式使用虚函数,并且所有 vtable 条目都设置为其最派生的版本。

    虽然可以将构造分解为三个部分(首先由每个构造函数更新 vtable,然后执行所有初始化程序,最后执行所有构造函数),但 C++ 标准委员会已决定不这样做。

    除了编译器构建器的简单性之外,事情的完成方式也有其他优势:如果您可以访问更多派生类成员(通过调用覆盖的 virtual 函数),它们就不会被初始化(甚至构造),因此任何派生类的函数都不应触及任何重要的数据成员,这比简单地说在构造期间不应调用虚函数更使一切复杂化。

    【讨论】:

    • 为了迂腐,重写函数发生在创作时,而不是在运行时......说“还没有”有点奇怪。
    • @KerrekSB 你是对的;我稍微改变了措辞,以更好地表达这一点。
    【解决方案2】:

    在构造函数内部,*this的动态类型为Foo,并没有定义函数Foo::bar。不要在构造函数中调用虚函数。 (除非您知道自己在做什么,在这种情况下您会知道如何提供定义。)

    【讨论】:

    • 正如我所想...他们添加/删除此功能是否有原因?我已经定义了Foo有一个抽象方法叫bar,为什么我不能从构造函数中调用它,反正它会存在?
    • @MarkusMeskanen:恐怕你的问题没有意义。仔细想想 C++ 对象是如何工作的(尤其是在存在基类的情况下的构造和破坏)......正如你所声称的那样,没有一个有用的“特性”概念。
    • 抱歉我缺乏知识...我无法实例化Foo 类型的对象,因此我必须有一个定义了bar 的子类,我们称之为@987654328 @。现在说SubFoo *sf = new SubFoo; 显然是SubFoo 的对象,它定义了bar。因此我无法理解为什么我不能只从Foo 的构造函数中调用bar,因为它总是会被定义。
    • @MarkusMeskanen:但是想想构造的顺序:首先构造所有基础子对象,然后构造所有数据成员,然后执行构造函数体。因此,在构建基础子对象时,派生对象甚至还不存在。
    • @KerrebSB 哦,对了……该死。有没有一种好方法可以在每个子类的实例上调用某些东西,还是我应该在每个子类的构造函数中手动添加bar();?
    猜你喜欢
    • 2016-05-10
    • 1970-01-01
    • 2015-06-29
    • 2011-01-23
    • 2015-02-28
    • 2012-10-31
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多