请在链接parashift之前阅读我的问题,我可以谷歌搜索,这是略有不同的情况。
这是不允许的
Child **cc;
Base ** bb = cc;
因为你可以做到
*bb = new OtherChild;
但如果我们有
Child **cc;
const Base *const *const bb = cc;
我不认为所有这些const都是我的例子所必需的,但只是为了确定..
我认为应该起作用的最小值是
Base *const *bb = cc;
然后你不能这样做
*bb = new OtherChild;
所以它应该是安全的。但为什么不允许呢?
答案 0 :(得分:6)
你混淆了两个案例:
const
虽然正式(在计算机科学理论中)这两个都涉及子类化,但事实是这些的C ++规则是不同的,因为const T
和T
的表示保证是同样,Base*
和Derived*
的表示通常因偏移而不同(但在涉及虚拟继承时可能会有根本的不同)。
在3.9.3中,标准声明
cv-qualified 或 cv-unqualified 版本的类型是不同的类型;但是,它们应具有相同的表示和对齐要求
假设:
struct Base {};
struct Derived : Base {};
Derived* pd = nullptr;
Base* pb = pd;
const
确实可以按照你建议的方式添加。
Base const* const* const cpcpcb = &pb;
Base* const* pcpb = &pb; // legal, pointer can't be changed
Base const* * ppcb = &pb; // illegal, one could try to rebind the pointer
// to a truly const object, then
// use pb to mutate the const object
但Derived*
和Base*
之间没有任何关系。存在转换,但Derived*
变量不一定包含Base
对象的地址(Base
对象中的Derived
子对象可能具有不同的地址)。因此你抱怨的那条线,以及你的问题所假设的有效线,都是非法的:
Base const* const* const cpcpcd = &pd; // error, there's no address of a Base
// to be found in pd
Base* const* pcpd = &pd; // error: again, there's no address of a Base
// stored in pd
正式地,标准在4.10中描述了这一点:
类型为“指向cv
D
的指针”的prvalue,其中D
是类类型,可以转换为类型为“指向cvB
的指针”的prvalue,其中{ {1}}是B
的基类。如果D
是B
的不可访问或模糊的基类,则需要进行此转换的程序格式不正确。 conversion是指向派生类对象的基类子对象的指针。空指针值被转换为目标类型的空指针值。
转换的结果是prvalue,它没有地址,你也无法创建指向它的指针。
答案 1 :(得分:1)
这是C ++语言强加的约束,因为指针类型的隐式转换基于继承规则(隐式转换为void *
除外)。
也就是说,鉴于以下程序,仅当T
是U
的基础时才允许分配:
T const *x;
U *y;
x = y;
但是,在你的情况下:
typedef Base *T;
typedef Child *U;
Base
和Child
之间的关系不会转移到指针类型。因此,“指向Base
”和“指向Child
的指针”之间没有继承关系,以允许您想要的直接赋值。
答案 2 :(得分:0)
我认为在你的等式中,你期望const
发挥比实际更大的作用。
const
是一个限定符,简单地说,它的作用是规范你访问类型或变量的方式。
重点是,如果语言本身(甚至没有考虑const
是什么)已经规定了某个特定的行为,那么您的具体案例与该常见问题解答报告的案例没有什么不同。
你处在一个非常简单的环境中,你应该用更简单的术语来思考。