C++ 向下转换对象的奇怪行为

Posted

技术标签:

【中文标题】C++ 向下转换对象的奇怪行为【英文标题】:strange behavior of C++ downcasting on object 【发布时间】:2021-12-20 14:08:43 【问题描述】:

我运行下面的代码将对象的父部分分配给子对象。 但正如内联所描述的,c 风格的向下转型表现出一些意想不到的事情。 那里发生了什么?请参考下面的评论。

    struct A 
    public:
        int i;
        A()  std::cout<<"A constructor called\r\n"; 
        ~A()  std::cout<<"A destructor called\r\n"; 
    ;

    struct B : public A 
        B()  std::cout<<"B constructor called\r\n"; 
        ~B()  std::cout<<"B destructor called\r\n"; 
    ;

    A a;
    B b;
    a.i = 1;
    (A)b = a;  // this code no effect and surprisingly the destructor of A is called.
               // there was no compiler warning (g++ (Ubuntu 11.2.0-7ubuntu2) 11.2.0)
    std::cout<<a.i<<std::endl;
    std::cout<<b.i<<std::endl;
    A& ra = b;
    ra = a;     // A portion of B is initialized as expected
    std::cout<<b.i<<std::endl;

此代码打印为

构造函数调用 一个名为的构造函数 B 构造函数调用 一个名为 1 0 1 调用 B 析构函数 一个名为的析构函数 一个名为

的析构函数

【问题讨论】:

(A)b 导致一个新的 A 被复制构造查看实时 - godbolt.org/z/ox11h76sd 。注意this 的值被输出以启用跟踪对象的创建/销毁。为了清楚起见,我还注释掉了作业。 好吧,对象的 c 风格向下转换会导致复制构造。这就是为什么不调用 A 的构造函数的原因。那么这是 c++ 行为吗? 【参考方案1】:

魔法就在这里: (A)b = a;

发生了什么:

    调用 A 的复制构造函数并创建一个新的 [class A object]。它是一个临时对象,在此语句之后它被破坏了。 所以打印 [一个名为 在临时对象上调用 A 的 operator=。它只影响临时对象而不是原始 b;

【讨论】:

我不明白为什么类型转换会产生一个时间对象。这是预期的 c++ 语句行为吗? 这是预期的;如果你不想要一个临时对象。你应该使用指针或引用。例如:(A&)b = a;如果使用 (A)b,则将 b 转换为 A 类,必须有一个新的内存块(临时对象)保存转换值 现在我明白了。但我认为语法不直观。因为其他原始类型在转换时不会生成时间对象。感谢您的友好回复。

以上是关于C++ 向下转换对象的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio C++ 编译器在局部变量对象上的奇怪行为

如何在 C++ 中正确地向下转换

C++中的虚函数(类的向上转换,和向下转换)

C++ 动态转换异常

向上强制转换和向下强制转换

向下转换为 pybind11 派生类