如何强制所有派生类实现虚方法?
假设您有一个用于类树的基类 Dep
。我希望每个叶类都实现一个虚拟方法 Dep* Dep::create()
。有什么办法可以强制执行吗?
注意:这里的问题是,可能有中间类(例如 class B : public A : public Dep
)偶然或因为实现此方法(A::create
)它们认为它们是叶类,但实际上它们自己是子类。
问题到这里就结束了。
上下文
如果你好奇我为什么需要这个;我有一个类 Master
,它具有未知具体类型的 Dep
对象。如果 Master
重复,我需要找到 Dep
实例的匹配克隆。接下来最好的事情是虚拟构造函数习惯用法,它恰恰引入了这个问题。
另外,我什至无法捕捉到这一点(除了可怕的崩溃),因为出于不明原因,比我有更多话要说的人在这个项目中禁止了 dynamic_cast
(也许这是一个很好的决定;但无论如何,这是一个完全不同的讨论)。
Say you have a base class Dep
for a tree of classes. There is a virtual method Dep* Dep::create()
that I want to be implemented by every single leaf class. Is there any way to enforce this?
Note: The problem here is that there could be intermediate classes (say class B : public A : public Dep
) implementing this method (A::create
) by accident or because they think they are leaf classes, but are in fact subclassed themselves.
The question ends here.
Context
If you are curious why I need this; I have a class Master
which has Dep
objects of unknown concrete type. If Master
is duplicated, I need to come up with a matching clone of the Dep
instance. Next best thing to do is the virtual constructor idiom, which introduces precisely this problem.
Additionally, I cannot even catch this (other then by crashing horribly), because for obscure reasons, people that have more to say than me, have outlawed dynamic_cast
in this project (perhaps this is a good decision; But anyways a completely different discussion).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
C++ 没有提供任何方法来阻止类从您的类继承,也没有办法使继承层次结构中的特定类实现方法。唯一的规则是,在特定类之上的继承层次结构中的某个位置(不一定在叶中),所有虚拟函数都必须具有该类可实例化的实现。
例如,
A
可以继承Def
并实现它的所有[纯]虚拟方法。那么如果B
继承自A
,它就不必实现任何东西。没有办法阻止这种情况发生。所以答案是否定的,没有办法强制执行。
C++ provides no way to keep a class from inheriting from your class, and there is no way to make a particular class in the inheritance hierarchy implement a method. The only rule is that somewhere in the inheritance hierarchy above a particular class (not necessarily in the leaf) all virtual functions must have an implementation for that class to be instantiatable.
For instance,
A
could inherit fromDef
and implement all it's [pure] virtual methods. Then ifB
inherits fromA
, it doesn't have to implement anything. There's no way to keep that from happening.So the answer is no, there is no way to enforce this.
使用奇怪的重复模板乐趣,您可以实现非常相似的目标:
使用
Cloneable::Create<,而不是从
Dep
派生并通过new MyType
实例化/代码>。由于Cloneable
派生自MyType
,因此您可以像使用任何MyType
一样使用该实例,只不过它现在是保证有Dep::clone
。此外,您的
Master
不应接受Dep
类型的实例,而应强制其为Cloneable
。 (用强制执行此操作的简单函数模板替换原始函数。)这保证了 master 内的任何Dep
都具有正确实现的clone
函数。由于
Cloneable
没有公共构造函数,因此无法继承它,但是您的实际MyType
可以像以前一样进一步继承和使用。Using curiously recurring template fun, you can achieve something quite similar:
Instead of deriving from
Dep
and instantiating vianew MyType
, useCloneable<MyType>::Create
. SinceCloneable<MyType>
is derived fromMyType
, you can use the instance the same way you would use anyMyType
, except that it is now guaranteed to haveDep::clone
.Additionally your
Master
should not accept an instance of typeDep
, but enforce that it is aCloneable<T>
. (Replace your orignial function by a simple function template that enforces this.) This guarantees that anyDep
inside the master has a correctly implementedclone
function.Since
Cloneable<MyType>
has no public constructor, it cannot be inherited, however your actualMyType
can be further inherited and used just as before.TPTB 是否禁止所有 RTTI,还是仅
dynamic_cast<>()
?如果您可以使用 RTTI,那么您可以强制该方法的存在作为调用它的后置条件:Did TPTB outlaw all RTTI, or only
dynamic_cast<>()
? If you can use RTTI, then you can enforce the existence of the method as a postcondition of calling it:如果您控制基类
AbstractDep
,那么您可以强制要求必须使用类模板WithCloning
创建具体的叶类。然后可以将这片叶子封印起来,使其无法被继承。或者更准确地说,不能创建派生类的实例。如果这些类需要的不仅仅是默认构造,那么大多数都需要另外解决。
一种解决方案是从
WithCloning
构造函数转发参数包(我的博客上有一个 C++98 实现示例,C++0x 直接支持它)。总而言之,要可实例化,该类必须是
WithCloning
。干杯&呵呵,,
If you control the base class
AbstractDep
then you can enforce that concrete leaf classes must be created by using a class templateWithCloning
. This leaf can then be sealed so that it cannot be inherited. Or more precisely, instances cannot be created of a derived class.If the classes require more than default construction then that most be solved additionally.
One solution is then to forward an argument pack from the
WithCloning
constructor (there is an example C++98 implementation on my blog, and C++0x supports that directly).Summing up, to be instantiable the class must be
WithCloning
.Cheers & hth.,
当你说它们未知时,我认为它们仍然继承自公共基类/接口,对吗?
我能想到的唯一可以用来强制的是虚拟基类添加,
因此您被迫覆盖,但这仅在运行时尝试在实例上调用克隆时检测到 缺少覆盖的类
即使您不允许使用dynamic_cast或RTTI,
,您仍然可以在构建上本地启用它以用于调试目的,如果这将帮助您找到有问题的类的typeid ,那么听起来您很熟悉克隆模式,但我会悄悄地将其发布在在这里,我们可以忘记它:
http://www.cplusplus.com/forum/articles/18757/
when you say that they are unknown, i presume they still inherit from a common base class /interface right?
only thing i can think of you can use to force is on the virtual base class add
so you are forced to override, but this is only detected at run-time when trying to call clone on a instance of a class that is missing the override
even if you are not allowed to use dynamic_cast or RTTI, you can still enable it for debug purposes locally on your build, if that will help you find the typeid of offending classes
it sounds like you are familiar with the clone pattern, but i'll post it quietly in here, and we can forget about it:
http://www.cplusplus.com/forum/articles/18757/