我有一个类,它继承自具有纯虚函数的类。
现在我需要添加另一个类,它不需要某些方法。我有一个想法是不实现这个方法,而不是在调用此方法时总是抛出异常,如下一个示例所示:
#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()不会被调用。
答案 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
类中声明它来保持纯虚拟。