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.假设没有调用构造函数但我仍然可以从该对象调用方法 - >这意味着我的类的成员仍未初始化?
对不起,如果这些问题有点愚蠢,但我觉得我现在的速度很慢.
这些是非常好的和重要的问题.
关于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"对象(即所有属性变量)都是随机存储器.该方法的代码将执行但使用随机内存,这是失败的.
我希望这可以解决一些问题.