繁体   English   中英

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

[英]Problem creating abstract class with no virtual pure methods C++

我想创建一个类,它是两个具有共同虚拟基类的类的子类。 此外,我希望这个类是抽象的(不能创建它的实例,也不需要调用虚拟基类的 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。

确实(自 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 }= default ,因此在这种情况下,析构函数定义需要在类定义之外。

虽然实际上,建议始终确保任何多态类(至少具有一个虚函数或虚基类)具有虚析构函数。 这使得delete指向具有不同动态类型的对象的基类类型的指针是合法的。 并且使用通常的 vtable 实现,将虚拟析构函数添加到已经是多态的类几乎没有成本。 按照这个建议,您还可以添加virtual ~CommonBaseClass() = default; CommonBaseClass ,然后其他类也自动具有虚拟析构函数。 然后你可以使用样式~TargetClass() override = 0; 用于声明纯虚析构函数。

您可以按如下方式使用纯虚拟析构函数。 即使它是纯虚拟的,您仍然需要实现它。 您不需要在派生类中声明析构函数。

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();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM