简体   繁体   English

我需要第二个接口 class 的虚拟析构函数吗?

[英]Do I need a virtual destructor for a second interface class?

I've got classes called "Base" and "Derived".我有名为“Base”和“Derived”的课程。

struct Base {
    Base() = default;
    virtual ~Base() = default;
    Base(const Base&) = delete;
    Base& operator=(const Base&) = delete;

    virtual void DoStuff() = 0;
};

The "Base" class needs virtual destructor and it's understandable. “基地” class 需要虚拟析构函数,这是可以理解的。 Also I don't allow copying of this class我也不允许复制这个 class

struct Derived : Base {
    Derived() = default;
    ~Derived() override = default;

    void DoStuff() override { /*...*/ }
};
int main()
{
    std::shared_ptr<Base> a = std::make_shared<Derived>();
    a->DoStuff();
    return 0;
}

Now let's introduce other classes called, I don't know, Callable and DerivedCallable现在让我们介绍其他的类,我不知道, CallableDerivedCallable

struct Callable
{
    virtual void Call() = 0;
};
struct DerivedCallable : Base, Callable
{
    DerivedCallable() = default;
    ~DerivedCallable() override = default;

    void DoStuff() override { /*...*/ }
    void Call() override { /*...*/ }
};
int main()
{
    std::shared_ptr<Base> a = std::make_shared<Derived>();
    a->DoStuff();

    {
        auto callableA = std::dynamic_pointer_cast<DerivedCallable>(a);
        if(callableA) {
            callableA->Call();
        }
    }

    std::shared_ptr<Base> b = std::make_shared<DerivedCallable>();
    b->DoStuff();
    
    {
        auto callableB = std::dynamic_pointer_cast<DerivedCallable>(b);
        if(callableB) {
            callableB->Call();
        }
    }

    return 0;
}

Derived does not inherit from Callable , so callableA is nullptr, thus the if statement won't execute the Call() function. Derived不继承自Callable ,因此callableA为 nullptr,因此 if 语句不会执行Call() function。

DerivedCallable on the other hand inherits from Callable and the std::dynamic_pointer_cast will increase the ref count of the object to 2, so when the callableB gets out of the scope the object won't be deallocated, only the refcount will decrease to 1 and then the main function will deallocate b .另一方面, DerivedCallable继承自Callablestd::dynamic_pointer_cast会将 object 的引用计数增加到 2,因此当callableB离开 scope 时,object 不会被释放,只有引用计数会减少到 1 并且然后主 function 将释放b

Does Callable need to have a virtual destructor? Callable是否需要有一个虚拟析构函数?

You only need a virtual destructor if you are ever going to delete a derived class object through a base class pointer.如果您要通过基指针 class 删除派生的 class object,则只需要一个虚拟析构函数。

Since you are using std::shared_ptr , you don't need any virtual destructors because the shared_ptr stores a correctly typed deleter (no matter how you cast it).由于您使用的是std::shared_ptr ,因此不需要任何虚拟析构函数,因为 shared_ptr 存储了正确类型的删除器(无论您如何转换)。

If you are ever going to own a DerivedCallable object with a Callable pointer ( std::unique_ptr<Callable> or something else that calls delete on a Callable* ), then it should have a virtual destructor.如果您打算拥有一个DerivedCallable object 和一个Callable指针( std::unique_ptr<Callable>或其他在Callable*上调用delete的东西),那么它应该有一个虚拟析构函数。 However, if you only ever have non-owning references with Callable* , then you don't strictly need the virtual destructor.但是,如果您只对Callable*进行非拥有引用,那么您并不严格需要虚拟析构函数。

Adding a virtual destructor when the class already has other virtual members is very cheap, so it's fine to add it so that you don't have to worry about accidentally delete -ing it wrong.在 class 已经有其他虚拟成员的情况下添加一个虚拟析构函数是非常便宜的,所以添加它就可以了,这样你就不用担心不小心delete -ing 错误了。

It depends.这取决于。 In theory, Base doesn't need a virtual destructor.理论上, Base不需要虚拟析构函数。 You need a destructor to be virtual when you lug around an object which has a different dynamic type than its static type.当你拖着 object 时,你需要一个析构函数是虚拟的,它的动态类型与其 static 类型不同。

In your example, you have Base pointer that really points to a Derivied object. If you were not to make ~Base() virtual, then, destroying that object would exhibit undefined behaviour -- likely by failing to destroy the Derived portion of the object.在你的例子中,你有一个真正指向DeriviedBase指针。如果你不使~Base()虚拟化,那么破坏 object 将表现出未定义的行为——可能是因为未能破坏 object 的Derived部分.

So, as long as you don't plan to have an (owning,) pointer to your object through a particular base class. that base class's destructor need not be virtual.因此,只要您不打算通过特定基类 class 拥有指向您的 object 的(拥有的)指针。该基类的析构函数不必是虚拟的。

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

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