虚拟方法在 C++0x 中不能"delete"吗?

Are virtual method not "delete"able in C++0x?

本文关键字:delete 不能 方法 C++0x 虚拟      更新时间:2023-10-16

当我们尝试使用deletevirtual方法时,错误消息似乎与场景有点错误。

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()

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

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

其中odr使用是即将发布的标准中的一个新术语,指的是之前的标准中明确使用的

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

我的看法是,错误消息使用中使用的术语来指代在这种特定情况下使用的odr,是的,这是一个违规的原因与您不能让非纯虚拟成员函数未实现的原因完全相同。

所有非纯虚拟函数都必须实现,无论您是否使用它们:

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函数成员的行上,说"这行不通。它会引起问题,因为这个实现必须存在。"

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

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

允许删除虚拟函数,但不允许覆盖它们。

§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;
};

演示

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

如果派生类无法实现,那么您可能不应该从一个需要某些东西的类派生。也许您一开始就不需要从该类派生。

这就像在说"我正在造一辆更好的车。这是一辆没有轮子的车。"你确定这是一部车吗?

还是你问这个只是出于好奇?