为啥在 C++ 中一个类的指针可以转换为另一个类的指针?

Posted

技术标签:

【中文标题】为啥在 C++ 中一个类的指针可以转换为另一个类的指针?【英文标题】:Why in C++ a pointer of one class can be casted to a pointer of another class?为什么在 C++ 中一个类的指针可以转换为另一个类的指针? 【发布时间】:2014-07-04 05:01:38 【问题描述】:
class A

public:
    void display()
    
        cout << "class A\n";
    
;

class B

public:
    void show()
    
        cout << "class B\n";
    
;

int main()

    A* aPtr = new A;
    B* bPtr = new B;
    B* bPtr2 = (B*) aPtr;

    return 0;

在上面的代码中,为什么在 C++ 中允许将一个类类型的指针转​​换为另一个类类型。由于这两个类仍然不相关,为什么B* bPtr2 = (B*) aPtr; 不会抛出编译时错误来转换不相关类型的指针。

【问题讨论】:

这是一个 C 风格的转换,编译器假定你知道你在做什么......尝试static_castdynamic_cast 看看会发生什么。 但是你没有使用 C++,那些是 C 风格的转换。 C++有static_castdynamic_castreinterpret_cast等类型转换操作符。 The C++ compiler should not allow valid C syntax wat。 FWIW,您始终可以使用 -Wold-style-cast 进行编译 @Surfing_SO 有很多事情会导致未定义的行为,但不需要编译器给出错误。事情就是这样。部分原因是历史原因,但很多时候是出于实际原因。语言工具的存在是为了帮助您避免导致未定义的行为,在这种情况下是 C++ 风格的强制转换。但是如果你下定决心要朝自己的脚开枪,C++ 不提供铠甲靴。 如果 C++ 编译器不编译 C 风格的强制转换,就无法再使用 C++ 编译器编译 C 代码,并且 C++ 将失去其主要功能之一(而且他们将拥有将其重命名为其他名称;)) 【参考方案1】:

C cast 语法会根据所涉及的类型做不同的事情。它可以做的事情之一是reinterpret_cast

这是您不应该使用 C 强制转换语法而坚持使用 C++ 强制转换的原因之一。使用 C++ 强制转换,您可以获得您要求的操作,而不是可能的其他操作。

c++ 编译器不应该允许这样做,并且应该抛出编译时错误。

C 兼容性是 C++ 成功的原因之一。 C 不应该有这种“多态”强制转换语法,但它确实有,而且 C++ 需要兼容。如果您正在编写新的 C++ 代码,则根本不应该使用旧语法。

在某些编译器上,您可以使用以下内容禁用 C 样式转换:-Werror=old-style-cast

【讨论】:

【参考方案2】:

您展示的示例被称为“不安全”或“未经检查”的演员表,这是完全正确的。它是从向后兼容 C 继承而来的低级结构。您不应该在现代 C++ 代码中使用它。

进行强制转换的正确方法是使用操作static_castdynamic_cast 或其亲属。详情请参阅相关问题When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?。

您可以通过使用选项-Wold-style-cast 强制 GCC 为这些类型转换显示警告。要将所有警告转换为错误,可以添加选项-Werror

【讨论】:

以上是关于为啥在 C++ 中一个类的指针可以转换为另一个类的指针?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我可以毫无错误地转换不相关类的指针?

为啥我不能在 AsyncTask 中为另一个类的 ListView 设置适配器?

关于C++基类、派生类的引用和指针

为啥我不能只用前向声明 C++ 声明一个类的静态成员?

C++ 强制转换自定义类的非指针实例

C++ Primer 5th笔记(chap 18 大型程序工具)类型转换与多个基类