c ++类型转换以获得访问权限

c++ type casting to gain access

我正在写一个 class(析构函数是虚拟的)哪些对象只能使用回收器 class 的对象删除。但是我发现任何人都可以在不了解我的回收者 class.

的情况下删除那个 class 的对象

请考虑以下示例:

class A
{
public:
    A() {qDebug() << "cTor: A";}

protected:
    virtual ~A() {qDebug() << "dTor: A";}
};

class B
{
public:
    virtual ~B() {cout << "dTor: B";}

protected:
    B() {cout << "cTor: B";}
};

A *a = new A;
delete (B*)a; // How is this possible !!??

输出:

cTor: A
dTor: A

如果可能,在不使 A 的析构函数的最终子 class 非虚拟的情况下,我可以做些什么来防止这种情况发生?

对于您上面提到的情况,您很幸运,B 的析构函数的地址与 A 的析构函数的地址在指针的偏移量方面相同。

虚拟析构函数只是对象vftable 中的另一个条目。只要访问内存地址就可以调用任何析构函数(不管他有多私有)。

这是一个代码示例,展示了这些事情是如何运作的:

class A
{
public:
    virtual void foo() {printf("foo !");};
};
class B
{
public:
    virtual void bar() {printf("bar !");};
}; 
...
A* a = new A();
((B*)a)->bar();

显然我可以通过调用 B->bar 来调用 A foo 而 B 甚至没有 A !!!!魔法 ?不。恰好 B->bar 与 A->foo 具有相同的地址。考虑到您的示例,A 的析构函数与 B 的析构函数具有相同的地址。

关于您的评论,如果这对于库开发 PoV 是安全的:

如果开发者不知道正确的转换方式不是你的问题,或者如果开发者真的想破坏你的库,他会的。您的工作是在正确使用事物时提供工作代码。如果库的用户想要从你的库中重新解释 cast 对象或使用其他非标准的、未定义的行为,你将无能为力(例如,一些随机的家伙想要使用 malloc 分配对象不是你的错......玩得开心和那个家伙!)。