struct A
{};
struct B : A
{
operator A() const = delete; // not work
};
int main()
{
B* p_derived = new B();
delete p_derived; // ok
// How to make the following two lines illegal?
A* p_base = new B();
delete p_base;
}
A
父类型的定义不能被改变,它的析构器也不能被删除。virtual
;所以 B
的对象不应该被一个指向 A
.
我不能用 struct B : protected A {};
因为我想 B
继承所有 public
成员 A
纹丝不动 public
.
在 C++的混搭模式这是个常见的问题。
除非mixin类通过指向原类的指针被多态删除,否则是可以的。
我的问题是:如何防止一个对象通过指向其父类的指针被删除?
如何防止一个对象通过指向其父类的指针被删除?
把A的destructor做成protected,那么子类就可以访问它来正确地毁灭B类型的对象,但是其他地方就不能访问了。
struct A
{
protected:
~A() {}
};
struct B : A
{
};
int main()
{
A* p_base = new B();
delete p_base; // This is now an error
}
如果你真的不能改变A,那么你可以这样做。
struct A
{
};
struct AA : A
{
protected:
~AA() {}
};
struct B : AA
{
};
int main()
{
AA* p_base = new B();
delete p_base; // How to make this a compile-time error?
}
但如果你通过A而不是AA来删除的话,这是不可行的。
根据你的问题的性质,你可以使用'#define A AA'或者其他类似的丑陋的黑客方法来使其在现有的代码库中工作。
struct A
{
};
struct AA : A
{
protected:
~AA() {}
};
#define A AA
struct B : A
{
};
int main()
{
A* p_base = new B();
delete p_base; // How to make this a compile-time error?
}
简而言之,你不能这样做。
考虑一下这样的函数
// definition of struct A
void func(A *p)
{
delete p;
}
和另一个编译单元的调用者
// definitions of struct A and B as in question
void func(A *);
void caller()
{
func(new B);
}
在这种情况下,在 func()
的类型完全不可见。B
更不用说指针的潜力了。p
其获得的实际积分为 B
. 由于 func()
是否 delete p
,函数 caller()
引起 func()
有未定义的行为。
在这种情况下,真正的解决方法是 B
不应继承 A
. 这一点已经有了强烈的暗示。A
没有 virtual
的destructor。 这将防止 caller()
呼叫 func()
带着 B *
.
如果你想 B
以提供与 A
的所有成员函数。B
所以他们转发到一个包含 A
. 例如:
struct B
{
B() : a() {};
void some_member(some_type arg)
{
a.some_member(arg); // assume A has this member that accepts these arguments
}
private:
A a;
};
很明显,有一些选项可供选择,如果 struct A
可以修改,但问题明确指出了不可能修改的用例。