指向派生类和基类之间的指针到指针转换?

16

关于下面的C++程序:

class Base { };

class Child : public Base { };

int main()
{   
    // Normal: using child as base is allowed
    Child *c = new Child();
    Base *b = c;

    // Double pointers: apparently can't use Child** as Base**
    Child **cc = &c;
    Base **bb = cc;

    return 0;
}

GCC 在最后一个赋值语句中产生了以下错误:

error: invalid conversion from ‘Child**’ to ‘Base**’

我的问题有两个:

  1. 为什么没有从Child **到Base **的隐式转换?
  2. 我可以使用C风格的强制转换或reinterpret_cast来使此示例正常工作。使用这些转换意味着放弃所有类型安全性。是否有任何我可以添加到类定义中以使这些指针隐式转换,或者至少以一种允许我使用static_cast的方式表达转换?

1
在许多编程语言中,这个问题的变体是SO上最常见的问题之一。但即使是对于同一种语言,每个人表达方式都略有不同,因此找到重复的问题可能会很困难。 - Daniel Earwicker
1
修复这个例子以避免不明确的转换将取决于你首先为什么使用指向指针的指针。 - aschepler
2个回答

27

如果允许这样做,你可以编写以下代码:

*bb = new Base;

而且 c 最终将指向一个 Base 实例。这是不好的。


小修正 - 他可以说 **bb = new Base(); 只有 *bb 是不被允许的。 - Phil
4
@Phil: new 返回一个指向类型为 *Base 的指针。bb 是类型为 **Base 的指针。因此,*bb 是正确的解引用级别。 - Amber
1
基本上,这个理由与关于char **char const **不等价的comp.lan.g.c FAQ是一样的:http://c-faq.com/ansi/constmismatch.html - Michael Burr
@Dav:抱歉,我以为你已经用Base **bb = new Base()替换了Base **bb = cc这一行。不知道我怎么会有这个想法,因为如果我这样想的话,你的Base *b = new Base()就是完全合法的。我的错误! - Phil
简单明了,今天的逻辑难题配额留给其他问题了。 :) - david van brink

1
指针是虚拟地址。通常您要对其进行的操作负责。使用msvc 2019,我可以将一个指针转换为基类,但不能将两个指针转换为基类。
example 1:

int p;
int *p1 = &p;
int **p2 = &p1; //OK

example 2:

struct xx {};
struct yy : public xx {};

yy p;
yy *p1 = &p;
xx **p2 = &p1; //Just a strange error

example 3:

struct xx {};
struct yy : public xx {};

yy p;
xx *p1 = &p; 
xx **p2 = &p1; //OK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接