自定义类/对象的构造函数和初始化

Tob*_*oby 9 c++ constructor initialization

我可以想象这个问题已经被问到了,但实际上我找不到任何合适的解决方案,所以请原谅这是一个多余的问题.

我有一个自定义类

class myClass_A
{
public:
    myClass_A();          // Constructor
    myFunction_A();       // Some function from Class A
};
Run Code Online (Sandbox Code Playgroud)

现在我有另一个自定义类,它有一个类型的成员 myClass_A

class myClass_B
{
public:
    myFunction_B();       // Some function from Class B

private:
    myClass_A m_instance; // Instance of Class A
}
Run Code Online (Sandbox Code Playgroud)

现在myFunction_B()myFunction_A()m_instance这样的方式调用方法:

myClass_B::myFunction_B()
{
    m_instance.myFunction_A();
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我编译我的代码(基本上就像我上面发布的示例),它将成功,没有任何警告或错误.所以我的问题是:

A.在这个例子中是否会调用构造函数?

B.我真的可以从未初始化的对象中调用方法吗?

C.假设没有调用构造函数但我仍然可以从该对象调用方法 - >这意味着我的类的成员仍未初始化?

对不起,如果这些问题有点愚蠢,但我觉得我现在的速度很慢.

Luc*_*asB 7

这些是非常好的和重要的问题.

关于A:

在执行构造函数体之前,C++生成的代码会自动调用类的所有聚合(即成员)对象的默认构造函数.基本上,它所做的是转换以下代码:

class myClass_B {
public:
    myClass_B()
    {
        m_instance.foo();
        m_pInstance->foo();
    }
private:
    myClass_A m_instance;
    myClass_A* m_pInstance;
};
Run Code Online (Sandbox Code Playgroud)

进入以下代码:

class myClass_B {
public:
    myClass_B()
        : m_instance()
        , m_pInstance()
    {
        m_instance.foo();
        m_pInstance->foo();
    }
private:
    myClass_A m_instance;
    myClass_A* m_pInstance;
};
Run Code Online (Sandbox Code Playgroud)

编译器自动插入的两行称为初始化列表,它在执行构造函数体之前调用每个聚合对象的默认构造函数.请注意,第二个m_pInstance()调用" 指针的默认构造函数",它创建一个未初始化的指针 ; 这几乎总是不是你想要的.请参阅下文,了解如何解决此问题.

现在让我们假设构造函数myClass_A具有签名myClass_A(int someNumber),即它需要一个参数.然后,C++ 无法自动生成初始化列表,myClass_B因为它不知道传递myClass_A构造函数的数字.它会向你抛出编译器错误,可能会抱怨缺少默认构造函数myClass_A.您必须自己编写初始化列表,例如:

class myClass_B {
public:
    myClass_B()
        : m_instance(21)
        , m_pInstance(new myClass_A(21))
    {
        m_instance.foo();
        m_pInstance->foo();
    }
private:
    myClass_A m_instance;
    myClass_A* m_pInstance;
};
Run Code Online (Sandbox Code Playgroud)

这是正确的代码,它myClass_A为参数调用值为21的构造函数someNumber.这也显示了如何正确初始化指针:使其指向一些新分配的对象.

关于B:

不像其他人说的,你可以!(试试看)

但它会导致意外行为,这不是你想要的.(包括它可能只在行星正确对齐时才能做你想要的.)它很可能会崩溃,但不能保证崩溃.这可能会导致您进行一些长时间的调试.如果您的编译器是智能的,它可能会识别并警告您,但它不会给您一个错误.

另请注意,对于具有默认构造函数的非指针聚合对象,调用默认构造函数,您将一切顺利.使用内置类型或指针时会出现问题.这是使用未初始化的变量,并且是导致错误的最常见原因之一.如果您的代码做了一些非常奇怪的事情,请始终检查您是否初始化了所有变量.它应该成为一个反射,在任何成员变量的初始化列表中放入一个条目,即使它正在调用默认构造函数.清楚地说明问题.

关于C:

是.有关详情,请参阅B. 有趣的是,如果你调用的方法不使用"this"指针(这包括不使用任何属性变量而不调用任何使用属性变量的方法),那么你的方法可以保证工作.在未初始化对象上调用方法时会发生的情况是方法中的"this"对象(即所有属性变量)都是随机存储器.该方法的代码将执行但使用随机内存,这是失败的.

我希望这可以解决一些问题.