在使用 `this` 创建新对象时调用委托构造函数

问题描述 投票:0回答:1

假设我有一个类,它通过将自身传递给多个成员指针来初始化它们(减少到仅

A
)。传递父窗口小部件是Qt中的常见做法。

class B : public Base{
public:
    B() :
        my_a(new A(this))
    {  ...  }
    A* my_a;
};

但是为了使其可测试,我想从外部设置这些指针,最好传入构造函数而不重复括号之间的所有内容。
可能看起来像这样:

class B : public Base{
    public:
    B() :
        B(new A(this))
    {   }
    B(A* a) :
        my_a(a)
    {  ...  }
    
    A* my_a;
};

B
的默认构造函数中,我们将其称为专用版本。但问题是它会导致未定义的行为 - 有时会崩溃,但有时会产生“不可能”的输出。我能够将范围缩小到
: B(new A(this))
部分 - 在使用
this
创建新对象时调用委托构造函数。

问题:在这种情况下是什么导致了 UB?在使用当前实例初始化新对象时是否可以使用委托构造函数?

如果没有任何效果,我将创建 2 个构造函数而不进行委托,并创建一个

init
方法来删除重复代码。

诗。将

Base
视为
QWidget
,而
A
B
是自定义小部件。

编辑: 这是一个可以编译的简短版本,但不同的运行可以产生不同的输出:

#include <iostream>
#include <string>

class Base 
{
    public:
    int get_int() const {return my_int;};
    
    int my_int = 5;
};

class A
{
public:
    A(Base* base = nullptr)
    {
        if(base != nullptr) {
            my_i = base->get_int();
        } else {
            my_i = 42;
        }
    }
        
    int my_i;
};

class B : public Base{
    public:
    B() :
        B(new A(this))
    {
        
    }
    B(A* a) :
        my_a(a)
    {}
    
    
    A* my_a;
};

int main ()
{
    B b;
    std::cout << b.my_a->my_i;
    return 0;
}
c++ qt constructor delegates
1个回答
0
投票

B() : B(new A(this))
中,必须创建
A
的实例作为评估委托构造函数的参数的一部分。这意味着它发生在
this
的任何初始化之前,包括调用基类类构造函数之前。在这种情况下,当构造
my_i
时,
A
尚未初始化。然后,您可以在调用
get_int();
时使用未定义的行为来读取未初始化的数据成员。

B() : my_a(new A(this))
中,
A
的实例是在成员初始化期间创建的,这总是在基类构造函数完成之后。在这种情况下,
my_i
在构造
A
之前初始化。

© www.soinside.com 2019 - 2024. All rights reserved.