C++抽象基类构造函数/析构函数 - 一般正确性
我想要一个 C++ Interface
,在继承时必须重写它(如果可能的话)。到目前为止,我有以下内容:
class ICommand{
public:
// Virtual constructor. Needs to take a name as parameter
//virtual ICommand(char*) =0;
// Virtual destructor, prevents memory leaks by forcing clean up on derived classes?
//virtual ~ICommand() =0;
virtual void CallMe() =0;
virtual void CallMe2() =0;
};
class MyCommand : public ICommand
{
public:
// Is this correct?
MyCommand(char* Name) { /* do stuff */ }
virtual void CallMe() {}
virtual void CallMe2() {}
};
我故意留下了我认为应该如何在 ICommand
中实现构造函数/析构函数。我知道如果删除注释,它将无法编译。请有人:
- 告诉我如何在
ICommand
中声明构造函数/析构函数以及如何在MyCommand
中使用它们 - 我是否在
ICommand 中正确设置了内容
以便MyCommand
必须覆盖CallMe
和CallMe2
。
I would like to have a C++ Interface
that must be overridden (if this is possible) when inherited. So far, I have the following:
class ICommand{
public:
// Virtual constructor. Needs to take a name as parameter
//virtual ICommand(char*) =0;
// Virtual destructor, prevents memory leaks by forcing clean up on derived classes?
//virtual ~ICommand() =0;
virtual void CallMe() =0;
virtual void CallMe2() =0;
};
class MyCommand : public ICommand
{
public:
// Is this correct?
MyCommand(char* Name) { /* do stuff */ }
virtual void CallMe() {}
virtual void CallMe2() {}
};
I have purposely left how I think the constructor/destructor's should be implemented in ICommand
. I know if I remove the comments, it will not compile. Please could someone:
- Show me how to declare the constructor/destructor's in
ICommand
and how they are meant to be used inMyCommand
- Have I set things up correctly in
ICommand
so thatMyCommand
must overrideCallMe
andCallMe2
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
C++ 不允许使用虚拟构造函数。一个简单的实现(没有虚拟构造函数)看起来像这样:
请注意,即使是纯虚拟析构函数 必须定义。
具体的实现看起来与您的示例完全相同:
您有几个
具体实现现在如下所示:
C++ does not allow for virtual constructors. A simple implementation (without the virtual constructor) would look something like this:
Note that even a pure virtual destructor must be defined.
A concrete implementation would look exactly like your example:
You have a couple of options for the constructor. One option is to disable the default constructor for
ICommand
, so that subclasses will have to implement a constructor that calls your ICommand constructor:A concrete implementation would now look something like this:
我知道这个已经很旧了,但这仍然是我第一次遇到这个问题。我就是这样做的。
接口头 foo.h:
是的,我知道“pragma Once”严格来说不是标准的,但它对我有用。
请注意,这里没有执行任何操作。没有构造函数:抽象类无法实例化。您可以通过工厂获得指向接口的指针。为了使虚拟函数调用起作用,必须通过指针来调用它们。虚拟析构函数是默认的,因为除了实现的多态化之外,它不需要做任何特殊的事情。工厂是一个免费功能。无需尝试将其设为静态成员或类似的成员。这不是java。
接口foo.cpp:
这里实现了工厂。请注意,工厂必须知道实现。这就是为什么我们不内联实现它:如果它是内联的,接口标头必须包含实现标头,并且通过它,实现的知识将“泄漏”到调用站点。
实现头foo_impl.h:
没什么特别的,只是重写了接口的虚函数。因为这个例子很简单,所以我将两个实现放在同一个文件中。在实际应用中情况会有所不同。
实现 foo_impl.cpp:
只需实现函数即可。
main.cpp:
通过枚举我们可以选择我们想要的实现。这些指针的类型为
Foo::Ptr
,它是std::unique_ptr
的别名。调用点根本不知道实现,只知道接口。输出将如预期:
I know this one is old, but it is still my first hit on this issue. This is how I would do it.
Interface header foo.h:
Yes I know that "pragma once" is strictly speaking not standard, but it works for me.
Note that nothing is implemented here. There is no constructor: an abstract class can not be instantiated. You get a pointer to the interface through the factory. For the virtual function calls to work, they must be called through a pointer. The virtual destructor is defaulted because it doesn't have to do anything special except polymorphing to the implementation. The factory is a free function. No need to try to make it a static member or something like that. This is not java.
Interface foo.cpp:
Here the factory is implemented. Notice that the factory has to know the implementation(s). That is why we don't implement it inline: if it was inline, the interface header would have to include the implementation header, and through it, knowledge of the implementation would "leak out" to the callsite.
The implementation header foo_impl.h:
Nothing special, just override the virtual functions of the interface. Because this exaple is simple, I put both implementations in the same files. In real applications that will be different.
The implementation foo_impl.cpp:
Just implement the functions.
The main.cpp:
Through the enum we can select the implementation we want. The pointers are of type
Foo::Ptr
, an alias forstd::unique_ptr<Foo>
. The callsite has no knowledge of the implementation at all, only the interface.The output will be as expected: