0

我有两个类:OuterClass 和 InnerClass。InnerClass 是 OuterClass 的私有成员,应使用 InnerClass(int) 构造函数在 OuterClass 构造函数中创建,但仍会调用默认的 InnerClass 构造函数。

内部类.hpp:

#ifndef INNERCLASS_HPP_
#define INNERCLASS_HPP_

class InnerClass {
public:
    int a;
    InnerClass();
    InnerClass(int);
    ~InnerClass();
};

#endif /* INNERCLASS_HPP_ */

内部类.cpp:

#include "InnerClass.hpp"
#include <iostream>

InnerClass::InnerClass() {
    a = 1;
    std::cout << "inner class constructed, a = " << a << std::endl;
}
InnerClass::InnerClass(int x) {
    a = x;
    std::cout << "inner class constructed, a = " << a << std::endl;
    //automatically: object InnerClass (a=3) is destroyed here...
}
InnerClass::~InnerClass() {
    std::cout << "inner class destructed, a = " << a << std::endl;
}

外部类.hpp:

#ifndef OUTERCLASS_HPP_
#define OUTERCLASS_HPP_

#include "InnerClass.hpp"

class OuterClass {
private:
    InnerClass blah;
public:
    OuterClass();
    ~OuterClass();
    void doSth();
};

#endif /* OUTERCLASS_HPP_ */

外部类.cpp:

#include "OuterClass.hpp"
#include <iostream>

OuterClass::OuterClass() {
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    blah = InnerClass(3);
    std::cout << "outer class constructed" << std::endl;
}

OuterClass::~OuterClass() {
    std::cout << "outer class destructed" << std::endl;
}

void OuterClass::doSth() {
    std::cout << "doSth: " << blah.a << std::endl;
}

主要的:

#include "OuterClass.hpp"
#include <iostream>

int main(int argc, char** argv) {
    std::cout << "Compiled at " << __TIME__ << std::endl;

    OuterClass x = OuterClass();
    x.doSth();

    std::cout << "done" << std::endl;
}

输出:

Compiled at 12:11:12
inner class constructed, a = 1 //this is unexpected
outer class constructing started, blah.a = 1 //this should be random data
inner class constructed, a = 3
inner class destructed, a = 3 //this is unexpected
outer class constructed
doSth: 3
done
outer class destructed
inner class destructed, a = 3

问题:

  1. 为什么在 OuterClass 构造函数的开头调用 InnerClass 的默认构造函数?
  2. 什么以及为什么在 OuterClass 构造函数中被破坏(“内部类被破坏,a = 3 //这是意外的”)?
  3. 似乎带有 a = 3 的 InnerClass 对象在 OuterClass 构造函数中被破坏了,为什么方法 doSth() 返回 3 而不是随机数据?
  4. 为什么删除 InnerClass() 构造函数(从 InnerClass.hpp 和 InnerClass.cpp 文件中)会导致 OuterClass.cpp 文件中的 OuterClass 构造函数出现编译时错误?该错误表示未找到 InnerClass() 定义。
4

5 回答 5

4

在构造函数中使用初始化列表。

OuterClass::OuterClass() : blah(3) {
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    std::cout << "outer class constructed" << std::endl;
}

自从你使用

OuterClass::OuterClass() {
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    blah = InnerClass(3);
    std::cout << "outer class constructed" << std::endl;
}

首先初始化 blah 将被称为默认 c-tor 和 in blah = InnerClass(3);,创建临时对象并将其复制到 blah,之后此字符串将被称为临时对象的析构函数。

于 2012-08-09T11:29:25.953 回答
2

1) 为什么在 OuterClass 构造函数的开头调用 InnerClass 的默认构造函数?

构建blah.

2)什么以及为什么在 OuterClass 构造函数中被破坏(“内部类被破坏,a = 3 //这是意外的”)?

你在InnerClass(3)构造函数的第二行构造的。您用来保存分配给 的值的那个blah。它被破坏,因为一旦分配完成,它就会超出范围blah

3) 似乎带有 a = 3 的 InnerClass 对象在 OuterClass 构造函数中被破坏了,为什么方法 doSth() 返回 3 而不是随机数据?

因为您将值分配3blah. 您的代码读取;

blah = InnerClass(3);

这将创建一个值为 3 的 InnerClass,然后将其值复制到blah. 所以两者blah和这个临时对象都具有相同的值。然后临时销毁。

如果您考虑一下,没有其他明智的方法可以实现这行代码。

4) 为什么删除 InnerClass() 构造函数(从 InnerClass.hpp 和 InnerClass.cpp 文件中)会导致 OuterClass.cpp 文件中的 OuterClass 构造函数出现编译时错误?该错误表示未找到 InnerClass() 定义。

因为那你一开始就没有办法建造blah。(正如其他人指出的那样,您可能希望blah首先正确构造一个初始化列表,而不是默认构造它,然后不得不去扭曲来修复它。)

于 2012-08-09T11:31:53.753 回答
0
OuterClass::OuterClass() /* default blah constructor is called here */ {
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    blah = InnerClass(3); /* a temporary InnerClass is created */
    std::cout << "outer class constructed" << std::endl;
} //temporary InnerClass destroyed (out of scope)

用于initializer list防止调用默认构造函数,如 ForEveR 建议的那样

于 2012-08-09T11:30:33.867 回答
0
  1. 当 OuterClass 的构造函数开始执行 body 时,必须构造所有成员。因为有一个blahInnerClass 成员,所以它被构造了。

  2. 当您blah在 OuterClass::OuterClass() 中分配时,会创建一个临时实例。这是事情的顺序:

    • 构造了一个临时的 InnerClass(3)。
    • 它被分配给blah
    • 临时值被破坏——这就是为什么有一个析构函数调用。
  3. 从 2 开始: blah 在上面 #2 中提到的分配中设置为 3。

  4. 有人会推断,在 C++ 中,如果您声明了一个专门的参数接受构造函数,则编译器不再在您背后创建默认构造函数。我现在懒得去研究标准中的相关地方,编辑们可以随时更正这一点。

如果您按以下方式检测 InnerClass,它会对您有所帮助:

  1. 保留一个静态实例计数器,并将其复制到每个实例。这样你就知道哪个实例正在报告事情。

  2. 手动写入InnerClass & operator=(const InnerClass &)以查看何时调用它。

于 2012-08-09T11:37:27.953 回答
0

(PS:你是从 Java World 到 C++ 的吗?)

输出解释:

inner class constructed, a = 1 //this is unexpected

首先使用默认构造函数构造 InnerClass

outer class constructing started, blah.a = 1 //this should be random data

这是在上一步中使用默认 ctor 构造的 InnerClass 的值

inner class constructed, a = 3

使用重载的 ctor 构造一个临时的 InnerClass 并分配给 blah 成员(调用隐式 operator= - 您可以通过重载 operator= 来检查)

inner class destructed, a = 3 //this is unexpected

上一步创建的临时 InerClass 被销毁

outer class constructed
doSth: 3
done
outer class destructed
inner class destructed, a = 3

答案:

为什么在 OuterClass 构造函数的开头调用 InnerClass 的默认构造函数?

因为你有 InnerClass 成员。您应该将其设为指针或使用初始化列表。

OuterClass::OuterClass() 
: blah(3)
{
    // automatically: blah = InnerClass();
    std::cout << "outer class constructing started, blah.a = " << blah.a << std::endl;
    // blah = InnerClass(3);
    std::cout << "outer class constructed" << std::endl;
}

什么以及为什么在 OuterClass 构造函数中被破坏(“内部类被破坏,a = 3 //这是意外的”)?

临时的 InnerClass 在这里被销毁。

似乎带有 a = 3 的 InnerClass 对象在 OuterClass 构造函数中被破坏了,为什么方法 doSth() 返回 3 而不是随机数据?

blah 成员现在拥有一个值为 3 的 InnerClass 对象的副本

为什么删除 InnerClass() 构造函数(从 InnerClass.hpp 和 InnerClass.cpp 文件中)会导致 OuterClass.cpp 文件中的 OuterClass 构造函数出现编译时错误?该错误表示未找到 InnerClass() 定义。

您的意思是删除默认构造函数。是的,错误是预期的,因为 blah 成员首先使用默认 ctor 创建。

于 2012-08-09T11:59:58.993 回答