C++ c++;键入casting以获得访问权限

C++ c++;键入casting以获得访问权限,c++,casting,virtual-destructor,C++,Casting,Virtual Destructor,我正在编写一个类(析构函数是虚拟的),只有使用回收器类的对象才能删除这些对象。但我发现,任何人都可以删除该类的对象,而不必知道我的recycler类 请考虑以下例子: class A { public: A() {qDebug() << "cTor: A";} protected: virtual ~A() {qDebug() << "dTor: A";} }; class B { public: virtual ~B() {cout <

我正在编写一个类(析构函数是虚拟的),只有使用回收器类的对象才能删除这些对象。但我发现,任何人都可以删除该类的对象,而不必知道我的recycler类

请考虑以下例子:

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 !!??

如果可能的话,在不使
A
的析构函数的最后一个子类变为非虚拟的情况下,我能做些什么来防止这种情况呢?

对于您上面提到的情况,您很幸运,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来调用foo,而B甚至没有A!!!!魔术没有。刚好B->bar和A->foo的地址相同。考虑您的示例,A的析构函数与B的析构函数具有相同的地址

关于您的评论,如果这是安全的图书馆发展PoV:


如果开发人员不知道正确的强制转换方法,这不是你的问题,或者如果开发人员真的想破坏你的库,他会的。您的工作是在正确使用东西时提供工作代码。如果库的用户想要重新解释库中的强制转换对象,或者使用其他非标准、未定义的行为(例如,一些随机的家伙想要使用malloc分配对象,这不是你的错……与该家伙打交道很开心!)。

delete(B*)a;///这怎么可能它不是。尝试使用正确的强制转换(如
静态强制转换
),您将看到。@πάνταYes。。但是为什么它同时适用于msvc++12和MingW4.92?未定义的行为就是未定义的行为。没有什么真正起作用。这显然是未定义的行为。请参阅@πάντα的答案,如果“未定义的行为”和“没有什么真正起作用”,那么我就没有什么可担心的了。谢谢
class A
{
public:
    virtual void foo() {printf("foo !");};
};
class B
{
public:
    virtual void bar() {printf("bar !");};
}; 
...
A* a = new A();
((B*)a)->bar();