有没有办法禁止我的类的子类化?
假设我有一个名为“Base”的类和一个名为“Derived”的类,它是 Base 的子类并访问 Base 的受保护方法和成员。
我现在想做的是使其他类不能子类化 Derived。 在 Java 中,我可以通过将派生类声明为“final”来实现这一点。 有一些 C++ 技巧可以给我同样的效果吗?
(理想情况下,我希望除 Derived 之外的任何类都不能子类 Base 。我不能将所有代码放入同一个类中或使用friend关键字,因为 Base 和 Derived 都是模板化的, Base 的模板参数比 Derived 少......)
Say I've got a class called "Base", and a class called "Derived" which is a subclass of Base and accesses protected methods and members of Base.
What I want to do now is make it so that no other classes can subclass Derived. In Java I can accomplish that by declaring the Derived class "final". Is there some C++ trick that can give me the same effect?
(Ideally I'd like to make it so that no class other than Derived can subclass Base as well. I can't just put all the code into the same class or use the friend keyword, since Base and Derived are both templated, with Base having fewer template arguments than Derived does....)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
从 C++11 开始,您可以将 Final 关键字(技术上是一个特殊标识符,因为它实际上不是关键字)添加到您的类中,例如,
您可以在 http://en.wikipedia.org/wiki/C++11#Explicit_overrides_and_final
As of C++11, you can add the final keyword (technically a special identifier since it is not actually a keyword) to your class, eg
You can read more about the final keyword at http://en.wikipedia.org/wiki/C++11#Explicit_overrides_and_final
您可以使用“
Derived
”的私有构造函数和用于实例化的公共静态 Create 函数You can have a private constructor for '
Derived
' and a public static Create function for instantiation禁止子类化的最简单方法是将构造函数设为私有:
编辑:感谢 Indeera 指出这需要一个静态工厂方法
The easiest way to prohibiting subclassing is by making the constructor private:
Edit: Thanks to Indeera for pointing out that this needs a static Factory method
没有简单干净的方法可以做到这一点。
标准库所做的只是使析构函数成为非虚拟的。 这并不能阻止子类化,但它向用户发出一个强烈的信号,表明它不是为继承而设计的,这意味着在使用派生类时必须非常小心。
但最终,您是否需要绝对使子类化不可能? 难道这还不足以表明“从这个类派生是一个坏主意”吗?
如果人们真的想的话,他们总是可以破解你的代码。 您能做的最好的事情就是让他们知道他们应该做什么和不应该做什么,并希望他们不会主动尝试破坏您的代码。
保护您的代码免受墨菲的侵害,而不是马基雅维利的侵害。 ;)
There is no simple and clean way to do it.
What the standard library does is simply make the destructor nonvirtual. That doesn't prevent subclassing, but it is a strong signal to users that it is not designed for inheritance, and it means you have to be very careful when using the derived class.
Ultimately though, do you need to absolutely make subclassing impossible? Isn't it good enough to indicate that "deriving from this class is a bad idea"?
People can always break your code if they really want to. The best you can do is make them aware of what they should and shouldn't do, and hope they won't actively try to break your code.
Protect your code against Murphy, not Machiavelli. ;)
由于您使用的是模板,我认为您关于防止除从 Base 派生到子类之外的任何类的问题的最后一部分可以使用适当的部分专业化来完成。
以下代码片段是我想出的,但所需的复杂性只会强化 jalf 的答案。 这值得么? 如果说这比制定我在实践中使用的技术更能帮助我理解部分专业化的话。
我使用 COMMON 来指示 Base 和 Derived 之间的共享模板参数,使用 EXTRA 来指示 Derived 具有的额外参数。 这些的实际数量可能是我碰巧分别为它们选择的一个和两个。
此代码已使用 gcc 4.3.2 进行测试。
请注意,友元声明的替代方法是在 Base 的部分特化中保护构造函数,但这将允许像 DishonestDerived 这样的类工作。
Since you are using templates I was thinking that the last part of your question about preventing any class other than Derived to subclass from Base could be done using appropriate partial specialisations.
The following code snippet is what I came up with but the complexity required only goes to reinforce the answer by jalf. Is it worth it? If anything this has helped me understand partial specialisation more than working out a technique I would ever use in practice.
I use COMMON to indicate a shared template parameter between Base and Derived and EXTRA to denote the extra parameters that you say Derived has. The actual numbers of these could be anything I just happened to have picked one and two for these respectively.
This code was tested with gcc 4.3.2.
Note that an alternative to the friend declaration would be to make the constructor protected in the partial specialisation of Base but then that would allow classes like DishonestDerived to work.