4

我来自 Java 背景,但之后我学习了 C++,并且已经使用它编程了几年(主要是调试和编写修复程序,而不是从头开始设计程序)。然而,我今天遇到了一个问题,坦率地说,我有点惊讶花了这么长时间才遇到它。

假设我有一个名为 Class1 的类,其头文件包含(以及其他代码):

class Class1 {
    private:
        Class2 object;
}

Class2 类没有指定默认构造函数。现在,在 Class1 构造函数中,我正在读取文件的二进制标头并使用从中解析的信息来初始化 Class2,如下面的伪代码所示:

Class1::Class1(std::string) {
    // Read some binary info from a file here

    // Parse that binary info

    object2 = Class2(info);

在 Java 中,因为它没有使用 RAII 范式,所以这是完全合法的。但是,由于 C++ 使用 RAII,所以在我做的时候,对象 2 已经用它的默认构造函数初始化了object2 = Class2(info);。我不能只调用那个构造函数(在 Class1 头文件中),因为我还没有需要创建的信息object。但是,我不能只object2对构造函数进行本地化,因为我需要其他函数才能看到/使用它。

显然这行不通。这些东西的标准方法是什么?我实际上想过只是将 Class1 更改为具有 Class2 指针,如下所示:

class Class1 {
    private:
        Class2* objectPointer;
}

然后调用*objectPointer = Class2(info). 但是,在我的情况下,“Class2”是一个 ifstream,似乎该operator=函数已被删除并且不适用于任何一种方法。

所以......我该怎么做?

4

4 回答 4

6

因为你object不是const,这都是完全合法的。但是,如果要objects在初始化阶段进行初始化,则必须提供信息。你可以这样做

 Class1::Class1(std::string file_name) : object(InfoFromFile(file_name)) {}

whereInfoFromFile()可以是独立函数(在 .cc 文件中的匿名命名空间中声明),也可以是 .cc 的静态成员函数Class1。如果需要比 file_name 更多的信息来生成所需的信息Class2,您可以将其提供给该函数。

于 2012-09-13T17:06:33.150 回答
5

如果“读取和解析”部分不需要构建对象,那么您可以将其移动到静态(或非成员)函数,并使用结果初始化成员:

Class1::Class1(std::string) :
    object2(read_class2_info(some_file))
{}

如果由于某种原因您确实无法将文件读取与对象构造分开,并且object2以后无法重新分配,那么您将需要使用指针。要创建对象,您可以使用new

objectPointer = new Class2(info);

然而,为了避免自己搞乱三法则,你应该避免自己管理动态对象,而是使用智能指针:

std::unique_ptr<Class2> objectPointer;

objectPointer.reset(new Class2(info));
于 2012-09-13T17:05:56.507 回答
2

我建议使用本地函数来执行读取二进制信息并直接在构造函数列表中初始化的位:

namespace {

InfoObject readInfo(std::string s)
{
// Read some binary info from a file here

// Parse that binary info
  return info;
}

}

Class1::Class1(std::string s)
: object(readInfo(s))
{
}

当然,使用指针也是一种选择。这也是为什么这在 Java 中更自然地工作的原因(每个用户类型在内部都是一个指针)。不过,您可能想使用智能指针。

于 2012-09-13T17:05:37.100 回答
1

我认为您必须object使用虚拟数据进行初始化,然后在解析后使用新数据对其进行更新。

像这样的东西:

Class1(std::string str)
 : object("some valid-but-meaningless data")
{
    // parse info
    object = Class2(info);

如果这不好,您可能必须在静态因子方法中进行解析,然后将信息传递给构造函数(您很可能将其设为私有)。像这样的东西:

Class1(Info info)
 : object(info)
{
    // whatever else you want
}

static Class1 create(std::string)
{
    // parse info
    return Class1(info);
}

编辑:我实际上更喜欢沃尔特的回答;在初始化中使用函数是个好主意。我只是把这个留在这里,你可以考虑一些替代的想法。

于 2012-09-13T17:06:44.287 回答