以下代码有效(在 ideone、Borland BCB 6 和 gcc 上)
#include <stdio.h>
class Base {
private:
Base **BPtr;
public:
Base(void *Ptr) {
BPtr = (Base **)Ptr;
*BPtr = this;
}
virtual ~Base() {
if(BPtr) *BPtr = NULL;
printf("Base aufgelöst\n");
}
};
class Child : public Base {
public:
Child(void *Var) : Base(Var) {}
~Child() {
printf("Child aufgelöst\n");
}
};
int main() {
Child *Ptr = NULL;
new Child(&Ptr);
printf("Childptr: %p\n", Ptr);
delete Ptr;
printf("Childptr: %p\n", Ptr);
return 0;
}
上面程序的输出是:
Childptr: 0x9cc0008
Child aufgelöst
Base aufgelöst
Childptr: (nil)
这正是我所期望和想要的。
我的问题很简单:这真的安全还是只是看起来有效?因为首先将 Child
类型的指针隐式转换为 void *
,然后将其转换为 Base **
或者这是否存在任何明显(或隐藏)的问题?
非常感谢。
编辑: 由于对我的意图似乎有点误解:
这个“黑客”的唯一目的是NULL
有问题的变量,一旦对象被销毁以保护我自己不小心忘记手动为NULL变量并可能在以后访问无效内存。
该变量必须且不会用于访问类的任何其他功能。
然而,我之前也尝试(和工作)的是以下内容:
void FreeFunc(void *Ptr) {
if(Ptr) {
Base **BPtr = (Base **)Ptr;
delete *Ptr; //Calls Destructors
*Ptr = NULL;
}
}
到目前为止,从我在这里收到的回复来看,哪个似乎更糟糕?
最佳答案
将 Child * 转换到 Base * 是安全的。将 Child** 转换到 Base** 并不是因为它们不相关。这样做的问题是,如果我转换为 void * 然后转换为 Base**,我现在可以将 Base * 分配给 Derived * 类型的指针,如下所示:
#include <iostream>
class Base
{
public:
virtual void Foo() { std::cout << "Base::Foo" << std::endl; }
};
class Child : public Base
{
public:
virtual void Foo() { std::cout << "Child::Foo" << std::endl; }
virtual void Bar() { std::cout << "Child::Bar" << std::endl; }
};
void main()
{
Child *d = new Child();
Base *b = d;
Child **d2 = &d;
Base **b2 = (Base **)(void *)d2; // Force it
*b2 = new Base(); // Whoops! Child *d now points to an instance of Base *
d->Bar();
}
关于c++ - 从指向子变量的指针转换为指向父变量的指针是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26359334/