缺少未使用的纯虚方法的实现时链接失败

时间:2011-03-18 12:08:14

标签: c++ linker polymorphism

我有一个类,它继承自具有纯虚函数的类。

现在我需要添加另一个类,它不需要某些方法。我有一个想法是不实现这个方法,而不是在调用此方法时总是抛出异常,如下一个示例所示:

#include <iostream>

class ibase {
    public:
        virtual void foo() = 0;
        virtual void boo() = 0;
};

class base1 : public ibase {
    public:
        virtual void foo(){ std::cout<<"base1::foo"<<std::endl; }
        virtual void boo(){ std::cout<<"base1::boo"<<std::endl; }
};

class base2 : public ibase {
    public:
        virtual void foo() { std::cout<<"base2::foo"<<std::endl; }
        virtual void boo();
};

int main()
{
    ibase *inst1 = new base1;
    ibase *inst2 = new base2;

    inst1->foo();
    inst1->boo();
    inst2->foo();
}

但是当我尝试使用下一个编译器选项进行编译时:

g++ dfg.cpp  -ansi -pedantic -Wall

这个例子产生了下一个输出(使用g ++ 4.3.0):

/tmp/ccv6VUzm.o: In function `base2::base2()':
dfg.cpp:(.text._ZN5base2C1Ev[base2::base2()]+0x16): undefined reference to `vtable for base2'
collect2: ld returned 1 exit status

有人可以解释链接失败的原因吗?方法boo()不会被调用。

6 个答案:

答案 0 :(得分:4)

创建base2的vtable - 您使用base2。 vtable引用boo() - 所以你需要定义它。

10.3 / 8:

  

在类中声明的虚函数   应被定义或宣布为纯粹的   (10.4)在该类中,或两者兼有;但不是   诊断是必需的(3.2)。

答案 1 :(得分:3)

单定义规则指出每个used函数必须只定义一次。术语used的定义包括以下行:

  

如果是,则使用虚函数   不纯洁

这意味着即使没有调用

,也必须定义所有非纯虚函数

答案 2 :(得分:1)

它失败了,因为内部vtable需要一个指向的地方。如果调用它并不重要,仍然会创建vtable。

为方法创建一个空体,你应该好好去。

答案 3 :(得分:1)

必须base2中实现该方法,没有办法解决它。多态性是一种运行时行为,链接器无法知道永远不会调用boo。你可以简单地在基类中提供一个虚拟实现,而不是如果它不是强制实现派生类中的方法那么它是纯虚拟的。

答案 4 :(得分:1)

boo实际上可能无法调用,但它用于构建base2的v-table。

你必须定义会发生什么行为,即某人有base2并在其上调用boo()(通过其基类指针),即使代码中没有实际调用它的点。这是实施ibase的合同的一部分。

设计当然是有缺陷的,如果你想要一个允许foo的类,那么应该有一个接口。

如果您的特定实例是一个无操作的调用,则该类是该类的行为。

答案 5 :(得分:0)

您忘了实施virtual void base2::boo ()。您必须实现它才能实例化base2类。否则,您可以通过不在base2类中声明它来保持纯虚拟。