2011-03-18 91 views
1

我有一个类,它从具有纯虚拟函数的类继承。当缺少未使用的纯虚拟方法的实现时,链接失败

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

#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 

本实施例中生产下一输出(使用克++ 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

为什么你不想抛出异常?它是检测它是否被调用的最安全的方法。另外,如果某些子类不需要它,则可能需要修改接口。 – 2011-03-18 12:15:06

+0

@Space_COwbOy我以为如果有人试图使用这种方法,我会得到一个编译器错误(就像你没有定义一个不应该使用的方法的模板专门化一样) – 2011-03-18 12:20:00

+1

纯虚函数的一般思想是**强制**派生类来实现这些功能。现在你宁愿不? :-) – 2011-03-18 17:05:59

回答

4

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

10.3/8:

在类 声明的虚拟函数将被定义,声明或纯 (10.4)在该类,或两者;但不需要 诊断(3.2)。

1

它失败了,因为内部虚拟表需要一个指向的位置。它是否被调用并不重要,该vtable仍然被创建。

为该方法创建一个空体并且您应该很好走。

1

必须实施base2中的方法,没有办法绕过它。多态性是一种运行时行为,连接器无法知道boo将永远不会被调用。您可以简单地在基类中提供虚拟实现,而不是在派生类中实现该方法时不强制实现该虚拟实现。

0

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

3

单一定义规则规定每个函数used必须精确定义一次。术语used的定义包括下面的行:

用于一个虚拟函数,如果它是 不是纯

这意味着,所有的非纯虚函数必须定义,即使它们不叫

1

boo实际上可能不会被调用,但它被用来构建base2的v-表。

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

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

如果您的特定实例是呼叫是无操作,那么这是该类的行为。

相关问题