虚拟方法在C ++ 0x中不能“删除”吗?

时间:2011-06-24 10:57:56

标签: c++ c++11 virtual

当我们尝试使用delete virtual方法时,错误消息似乎与方案相差甚远。

prog.cpp:4:16: error: deleted function 'virtual void Test::foo()'
prog.cpp:8:2: error: used here

代码

struct Test : public Base
{
  Test() {}
  virtual void foo () = delete;  // error
};

virtual方法不是delete能够出于同样的原因,为什么它们不能在C ++ 03中保持未实现状态?有没有办法提到Test故意不实施virtual foo()

5 个答案:

答案 0 :(得分:9)

术语 use 在标准中有一个具体的定义,特别是对于虚函数, odr-used 的定义是:

  

§3.2/ 2(C ++ 0x FDIS)[...]虚拟成员函数如果不是纯粹的,则会被使用。[...]

其中 odr-used 是即将推出的标准中的一个新术语,指的是前一个标准名为使用

  

§3.2/ 2(当前标准)[...]如果虚拟成员函数不纯,则使用虚拟成员函数。[...]

我的看法是,在这种特殊情况下,错误消息使用术语使用来引用 odr-used ,是的,这是违规的原因是完全相同的原因,你不能使非纯虚拟成员函数未实现。

答案 1 :(得分:3)

必须实现所有非纯虚函数whether you use them or not

struct Test
{
  Test() {}
  virtual void foo();
};

int main() {
   Test* t = new Test;
   // ^ it seems to have to be dynamic allocation to coerce the error out
}

/* Output:
/home/Y3oGMf/ccOLuYWf.o: In function `main':
prog.cpp:(.text+0x17): undefined reference to `vtable for Test'
collect2: ld returned 1 exit status
*/

由于类似的原因,我认为您正在看到有关使用已删除功能的稍微奇怪的错误消息。这只是因为内部的工作方式。您尝试delete virtual函数成员的行可能会出现更明智的错误消息,说“这不会起作用。它会导致问题,因为此实现必须< / em>存在。“

无论如何delete接口函数都没有意义。继承增加了功能;它不会带走它。注意如何使成员函数 pure virtual禁止整个类被实例化:派生类必须重新实现该功能,以免它丢失。

答案 2 :(得分:2)

我的理解是delete关键字用于删除编译器生成的默认实现。对于虚方法,编译器不会生成默认实现。

答案 3 :(得分:1)

允许删除虚拟函数,但不会重载它们。

§10.3(11)说:

  

在类中声明的虚函数应在该类中定义,或声明为纯(10.4),或两者兼而有之;但不需要诊断(3.2)。

§8.4.1表示已定义删除的功能

并且§10.3(16)说:

  

具有已删除定义(8.4)的函数不得覆盖没有已删除定义的函数。同样,没有删除定义的函数不得覆盖具有已删除定义的函数。

最后一条规则的目的是确保在编译时可以诊断对已删除函数的调用。

因此以下代码形成错误:

struct Base {
    virtual void foo();
};
struct Derived : public Base {
    virtual void foo() = delete;
};

但以下代码形式良好:

struct Base {
    virtual void foo() = delete;
};
struct Derived : public Base {
    virtual void foo() = delete;
};

DEMO

OP有一个编译器错误或QoI问题(很难分辨哪个,因为他没有发布整个代码),这个问题已被修复。

答案 4 :(得分:0)

如果你的派生类无法实现它,也许你不应该从一个需要某些东西的类派生出来。可能你不需要从那个类派生出来。

这就像是在说“我正在制造一辆更好的汽车。这种汽车有点像车,但没有实现车轮。”你确定它首先是一辆汽车吗?

或者你是出于好奇而问这个?