从Derived **转换为Base * const *

时间:2013-08-07 11:26:06

标签: c++

请在链接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;

所以它应该是安全的。但为什么不允许呢?

3 个答案:

答案 0 :(得分:6)

你混淆了两个案例:

  • 添加const
  • Upcasts

虽然正式(在计算机科学理论中)这两个都涉及子类化,但事实是这些的C ++规则是不同的,因为const TT的表示保证是同样,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是类类型,可以转换为类型为“指向cv B的指针”的prvalue,其中{ {1}}是B的基类。如果DB的不可访问或模糊的基类,则需要进行此转换的程序格式不正确。 conversion是指向派生类对象的基类子对象的指针。空指针值被转换为目标类型的空指针值。

转换的结果是prvalue,它没有地址,你也无法创建指向它的指针。

答案 1 :(得分:1)

这是C ++语言强加的约束,因为指针类型的隐式转换基于继承规则(隐式转换为void *除外)。

也就是说,鉴于以下程序,仅当TU的基础时才允许分配:

T const *x;
U *y;
x = y;

但是,在你的情况下:

typedef Base *T;
typedef Child *U;

BaseChild之间的关系不会转移到指针类型。因此,“指向Base”和“指向Child的指针”之间没有继承关系,以允许您想要的直接赋值。

答案 2 :(得分:0)

我认为在你的等式中,你期望const发挥比实际更大的作用。

const是一个限定符,简单地说,它的作用是规范你访问类型或变量的方式。

重点是,如果语言本身(甚至没有考虑const是什么)已经规定了某个特定的行为,那么您的具体案例与该常见问题解答报告的案例没有什么不同。

你处在一个非常简单的环境中,你应该用更简单的术语来思考。