问题创建抽象类,没有虚拟纯方法C++

发布于 2025-02-10 08:18:30 字数 1094 浏览 1 评论 0原文

我想创建一个具有共同虚拟基类的两个类的子类。此外,我希望此类是抽象的(无法创建其实例,但也不需要称呼虚拟基类的CTOR)。

示例代码:

#include <cstdio>
class CommonBaseClass {
public:
    virtual void DoSomething() = 0;
    virtual void DoSomethingElse() = 0;

    CommonBaseClass(int a) {}
};

class ClassA : public virtual CommonBaseClass {
public:
    virtual void DoSomething() override {
        printf("SOMETHING\n");
    }
    ClassA() {};
};

class ClassB : public virtual CommonBaseClass {
public:
    virtual void DoSomethingElse() override {
        printf("SOMETHING ELSE\n");
    }
    ClassB() {};
};

class TargetClass : //I will never instantiate this class
    public ClassA,
    public ClassB
{
public:
    TargetClass() : ClassA(), ClassB() {} //I don't want to call the CommonBaseClass ctor
};

class SubclassOfTarget :
    public TargetClass
{
public:
    SubclassOfTarget(int a) : CommonBaseClass(a), TargetClass()
    {}
};

int main()
{
    SubclassOfTarget c(15);
    c.DoSomething();
    c.DoSomethingElse();
}

如果您尝试编译此程序,您会发现编译器抱怨targetClass不调用CommonBaseclass的CTOR。

I want to create a class that is a subclass of two classes that have a common virtual base class. Furthermore, I want this class to be abstract (not be able to create instances of it, but also not needing to call the ctor of the virtual base class).

Sample code:

#include <cstdio>
class CommonBaseClass {
public:
    virtual void DoSomething() = 0;
    virtual void DoSomethingElse() = 0;

    CommonBaseClass(int a) {}
};

class ClassA : public virtual CommonBaseClass {
public:
    virtual void DoSomething() override {
        printf("SOMETHING\n");
    }
    ClassA() {};
};

class ClassB : public virtual CommonBaseClass {
public:
    virtual void DoSomethingElse() override {
        printf("SOMETHING ELSE\n");
    }
    ClassB() {};
};

class TargetClass : //I will never instantiate this class
    public ClassA,
    public ClassB
{
public:
    TargetClass() : ClassA(), ClassB() {} //I don't want to call the CommonBaseClass ctor
};

class SubclassOfTarget :
    public TargetClass
{
public:
    SubclassOfTarget(int a) : CommonBaseClass(a), TargetClass()
    {}
};

int main()
{
    SubclassOfTarget c(15);
    c.DoSomething();
    c.DoSomethingElse();
}

If you try to compile this program, you will see that the compiler complains that TargetClass does not call the ctor of CommonBaseClass.

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

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

发布评论

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

评论(2

赠意 2025-02-17 08:18:30

确实(因为C ++ 11),抽象类的构造函数无需初始化其虚拟基类。在没有任何特定启用的虚拟功能的情况下,制作班级抽象的通常方法是使破坏者纯虚拟。

通过此更改,您的程序编译:

class TargetClass : //I will never instantiate this class
    public ClassA,
    public ClassB
{
public:
    TargetClass() : ClassA(), ClassB() {} //I don't want to call the CommonBaseClass ctor

    virtual ~TargetClass() = 0;
};
TargetClass::~TargetClass() = default;

请注意,即使它是纯粹的,也必须定义破坏者。由于一份声明不能同时具有= 0{ body }} = = =默认值在这种情况下,需要超出班级定义。

尽管实际上,建议始终确保任何多态类别(至少具有一个虚拟功能或虚拟基类)具有虚拟破坏者。这使得delete基本类类型的指针指向具有不同动态类型的对象的指针是合法的。而且,使用通常的VTable实现,将虚拟破坏者添加到已经是多态性的类中几乎没有成本。遵循此建议,您还将添加Virtual〜commonBaseclass()= default; commonbaseclass ,然后其他类也自动具有虚拟击路仪。然后,您可以使用样式〜tar​​getClass()Override = 0;来声明纯虚拟驱动器。

It's true (since C++11) the constructors of an abstract class don't need to initialize their virtual base classes. The usual way to make a class abstract without any specific unimplemented virtual functions is to make the destructor pure virtual.

With this change, your program compiles:

class TargetClass : //I will never instantiate this class
    public ClassA,
    public ClassB
{
public:
    TargetClass() : ClassA(), ClassB() {} //I don't want to call the CommonBaseClass ctor

    virtual ~TargetClass() = 0;
};
TargetClass::~TargetClass() = default;

Note the destructor must be defined, even though it is pure. Since one declaration can't have both = 0 and a {body} or = default, that destructor definition in this case needs to be outside the class definition.

Though actually, it's recommended to always make sure any polymorphic class (having at least one virtual function or virtual base class) has a virtual destructor. This makes it legal to delete a pointer of base class type pointing at an object with a different dynamic type. And with the usual vtable implementations, there's nearly no cost to add the virtual destructor to a class which is already polymorphic. Following this advice, you would also add virtual ~CommonBaseClass() = default; to CommonBaseClass, and then the other classes automatically also have virtual destructors. And then you might use the style ~TargetClass() override = 0; for the declaration of the pure virtual destructor.

雪化雨蝶 2025-02-17 08:18:30

您可以使用如下的纯虚拟驱动器。即使它是纯虚拟的,您仍然需要实施它。您不需要在派生类中声明破坏者。

class TargetClass : //I will never instantiate this class
    public ClassA,
    public ClassB
{
public:
    TargetClass() : ClassA(), ClassB() {} //I don't want to call the CommonBaseClass ctor
    virtual ~TargetClass() = 0;
};

class SubclassOfTarget :
    public TargetClass
{
public:
    SubclassOfTarget(int a) : CommonBaseClass(a), TargetClass()
    {}
};

TargetClass::~TargetClass()
{}

int main()
{
    SubclassOfTarget c(15);
    c.DoSomething();
    c.DoSomethingElse();
}

You can use a pure virtual destructor as follows. Even although it is pure virtual, you still need to implement it. You do not need to declare destructors in the derived classes.

class TargetClass : //I will never instantiate this class
    public ClassA,
    public ClassB
{
public:
    TargetClass() : ClassA(), ClassB() {} //I don't want to call the CommonBaseClass ctor
    virtual ~TargetClass() = 0;
};

class SubclassOfTarget :
    public TargetClass
{
public:
    SubclassOfTarget(int a) : CommonBaseClass(a), TargetClass()
    {}
};

TargetClass::~TargetClass()
{}

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