gpt4 book ai didi

c++ - 从具有非虚拟析构函数的类中私有(private)继承是否安全?

转载 作者:IT老高 更新时间:2023-10-28 22:29:27 32 4
gpt4 key购买 nike

我知道,公共(public)继承通常是安全的,因为当 delete 基类指针时,编译器只生成代码来调用基类的析构函数,并且派生类的那个没有被调用。

但是对于私有(private)继承,客户端不能将派生类指针转换为基类指针(因为私有(private)继承不模拟 is-a 关系),所以 delete总是在派生类的指针上使用,编译器应该能够看到还有一个基类并调用它的析构函数。

我做了这个测试:

#include <iostream>

struct BaseVirtual
{
virtual ~BaseVirtual()
{
std::cout << "BaseVirtual's dtor" << '\n';
}
};

struct BaseNonVirtual
{
~BaseNonVirtual()
{
std::cout << "BaseNonVirtual's dtor" << '\n';
}
};

struct DerivedPrivVirtual: private BaseVirtual
{
static void f()
{
BaseVirtual * p = new DerivedPrivVirtual;
delete p;
}

~DerivedPrivVirtual()
{
std::cout << "DerivedPrivVirtual's dtor" << '\n';
}
};

struct DerivedPrivNonVirtual: private BaseNonVirtual
{
static void f()
{
BaseNonVirtual * p = new DerivedPrivNonVirtual;
delete p;
}

~DerivedPrivNonVirtual()
{
std::cout << "DerivedPrivNonVirtual's dtor" << '\n';
}
};

int main()
{
std::cout << "With explicit derived pointer type:" << '\n';
{
DerivedPrivVirtual * derivedPrivVirtual = new DerivedPrivVirtual;
DerivedPrivNonVirtual * derivedPrivNonVirtual = new DerivedPrivNonVirtual;

delete derivedPrivVirtual;
delete derivedPrivNonVirtual;
}
std::cout << '\n';

std::cout << "With base pointer type:" << '\n';
{
// Client code can't cast Derived to Base when inherit privately.
//BaseVirtual * derivedPrivVirtual = new DerivedPrivVirtual;
//BaseNonVirtual * derivedPrivNonVirtual = new DerivedPrivNonVirtual;

//delete derivedPrivVirtual;
//delete derivedPrivNonVirtual;
}
std::cout << '\n';

std::cout << "Inside derived class itself:" << '\n';
{
DerivedPrivVirtual::f();
DerivedPrivNonVirtual::f();
}
std::cout << '\n';

std::cout << "With non-dynamic variables:" << '\n';
{
DerivedPrivVirtual derivedPrivVirtual;
DerivedPrivNonVirtual derivedPrivNonVirtual;
}
std::cout << '\n';
}

GCC 4.7.1 和 CLang 3.1 提供相同的输出。除非派生类本身将派生类指针强制转换为基类并删除,否则将调用派生类构造函数。

除了这种看起来很不常见且很容易避免的情况(类的作者是唯一可以造成伤害的人,但它确实知道它是从哪个类派生出来的),我可以断定它是安全的吗?

With explicit derived pointer type:
DerivedPrivVirtual's dtor
BaseVirtual's dtor
DerivedPrivNonVirtual's dtor
BaseNonVirtual's dtor

With base pointer type:

Inside derived class itself:
DerivedPrivVirtual's dtor
BaseVirtual's dtor
BaseNonVirtual's dtor <-- Only a problem inside the class itself

With non-dynamic variables:
DerivedPrivNonVirtual's dtor
BaseNonVirtual's dtor
DerivedPrivVirtual's dtor
BaseVirtual's dtor

额外问题: protected 继承呢?我想伤害的能力不再是直接派生类的作者的特权,而是层次结构中任何类的作者的特权。

最佳答案

无论继承是公有的还是私有(private)的,都不会影响代码的安全性,它只是限制了它可以安全/不安全地使用的范围。您有相同的基本问题:如果您的类或您的类的 friend 将您的类型的对象传递给一个接口(interface),该接口(interface)采用指向没有虚拟析构函数的基的指针,并且如果该接口(interface)获得您的对象的所有权,那么您正在创建 undefined行为。

设计中的问题是,根据您的问题, BaseNonVirtual 并非旨在扩展。如果是,它应该有一个公共(public)的虚拟析构函数,或者一个 protected 非虚拟析构函数,确保没有代码能够通过指向基的指针对派生对象调用 delete。

关于c++ - 从具有非虚拟析构函数的类中私有(private)继承是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12464633/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com