强制虚拟析构函数? C++

发布于 2024-09-19 03:21:06 字数 779 浏览 7 评论 0原文

我在 C++ Faq lite: How do I Define a base class so every class inheriting it is required to Define a destructor? 中没有看到这个问题的答案:

How do I Define a base class so every class inheriting it is required to Define a destructor?

我尝试运行这个程序

struct VDtor { virtual ~VDtor()=0;  };
struct Test:VDtor { virtual ~Test(){}  };
int main() { delete new Test; return 0; }

http://codepad.org/wFcE71w3 出现错误

In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD0Ev+0x1e): undefined reference to `VDtor::~VDtor()'
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD1Ev+0x1e): undefined reference to `VDtor::~VDtor()'

那么,这可能吗?

I didn't see the answer to this in the C++ Faq lite:

How do I define a base class so every class inheriting it is required to define a destructor?

I tried running this program

struct VDtor { virtual ~VDtor()=0;  };
struct Test:VDtor { virtual ~Test(){}  };
int main() { delete new Test; return 0; }

http://codepad.org/wFcE71w3
With the error

In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD0Ev+0x1e): undefined reference to `VDtor::~VDtor()'
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD1Ev+0x1e): undefined reference to `VDtor::~VDtor()'

So, is it possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅忆流年 2024-09-26 03:21:06

从某种意义上说,这是“可能的”(如果您的目标是派生类保持抽象,否则)。但它不会给出您想要的结果:因为如果程序员没有这样做,编译器将隐式地创建析构函数本身。

因此不可能强制派生类的作者显式声明构造函数。

(编辑:就像@chubsdad notes 指出的那样,您的特定代码中的错误是因为您需要定义基类的显式声明的析构函数)。


编辑< /strong>:只是为了好玩,有些情况需要显式声明的构造函数。考虑以下

struct Viral {
  struct Dose { };
protected:
  ~Viral() throw (Dose) { }
};

struct Base {
  virtual ~Base() throw() { }
};

struct Derived : Base, Viral { };

代码此代码将无法编译,因为隐式声明的 ~Derived 将具有比 ~Base 更宽松的异常规范 throw (Dose) code> 有 - 所以它违反了覆盖者不得有更宽松的异常规范的要求。您需要适当地显式声明析构函数

struct Derived : Base, Viral { ~Derived() throw() { } };

但这并不是真正解决您的问题,因为派生类需要“合作”从 Viral 派生或将其作为非静态数据成员。它也非常丑陋:)


编辑:以下似乎是一种符合标准的 Clang 和 GCC 方法

struct Viral {
  struct Dose { };
protected:
  ~Viral() throw (Dose) { }
};

struct Base : virtual Viral {
  virtual ~Base() throw() { }
};

(从 v4.6 开始)拒绝任何具有隐式声明析构函数的 Base 派生类,因为它具有不兼容的异常规范(标准规定,任何派生类都应直接调用 ~Viral,而不是通过调用 ~Base 间接调用)。科莫接受这一点,但我强烈怀疑它在这方面不符合规定。

It is "possible" in some sense (if your goal was that the derived class stays abstract otherwise). But it won't give the result you would like: Because the compiler will create a destructor itself implicitly if the programmer hasn't done so.

It's therefor not possible to force the derived class' author to explicitly declare a constructor.

(edit: Like @chubsdad notes noted, the error in your particular code is because you need to define the explicitly declared destructor of the base class).


Edit: Just for fun, there are situations that necessiate an explicitly declared constructor. Consider the following

struct Viral {
  struct Dose { };
protected:
  ~Viral() throw (Dose) { }
};

struct Base {
  virtual ~Base() throw() { }
};

struct Derived : Base, Viral { };

This code won't compile because the implicitly declared ~Derived will have an exception specification throw (Dose) which is looser than what ~Base has - so it violates the requirement that overriders shall not have a looser exception specification. You will need to explicitly declare the destructor appropriately

struct Derived : Base, Viral { ~Derived() throw() { } };

But this is not really a solution to your problem, because derived classes need to "cooperate" into either deriving from Viral or putting it as a non-static data member. It's also very ugly :)


Edit: The following seems to be a Standard conforming way to do it

struct Viral {
  struct Dose { };
protected:
  ~Viral() throw (Dose) { }
};

struct Base : virtual Viral {
  virtual ~Base() throw() { }
};

Clang and GCC (starting with v4.6) reject any derived class of Base that has an implicitly declared destructor, because it has an incompatible exception specification (any derived class shall call ~Viral directly, instead of indirectly by calling ~Base, the Standard says). Comeau accepts this, but I strongly suspect that it is non-conforming in this regard.

猫烠⑼条掵仅有一顆心 2024-09-26 03:21:06

无论如何,每个类都有一个析构函数。在基础中声明虚拟析构函数可确保子级将拥有虚拟析构函数。这并不意味着编码人员需要显式声明析构函数——无论如何,这不是一件好事。它的意思是,如果声明了析构函数,它将是虚拟的。

Every class has a destructor, regardless. Declaring a virtual destructor in the base ensures that children will have virtual destructors. This doesn't mean that the coder will need to explicitly declare a destructor -- that wouldn't be a good thing, anyhow. All it means is that, if a destructor is declared, it will be virtual.

最单纯的乌龟 2024-09-26 03:21:06
struct VDtor { virtual ~VDtor()=0;  };
VDtor::~VDtor () { } // <== Implementation.
struct Test:VDtor { ~Test(){}  };
int main() { delete new Test; return 0; }

要修复该错误,您必须像上面一样实际实现 VDtor::~VDtor() 。

struct VDtor { virtual ~VDtor()=0;  };
VDtor::~VDtor () { } // <== Implementation.
struct Test:VDtor { ~Test(){}  };
int main() { delete new Test; return 0; }

To fix the error you have to actually implement the VDtor::~VDtor() like above.

泡沫很甜 2024-09-26 03:21:06

当 Test 被析构时,它将调用它的基类析构函数,该析构函数不存在。如果没有必要的销毁逻辑,您应该将其声明为空。

When Test is destructed, it will call it's base class destructor, which doesn't exist. You should just declare it empty if you have no necessary destruction logic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文