构造函数体中的对象初始化

时间:2013-11-29 11:01:41

标签: c++ oop

我编写了一个类来根据模式执行unordered_map中存储的数据输出。我希望这个模式在创建时传递给对象,并且在对象生存期内不会改变。

这是我先写的课程:

class Format {
public:
  Format(const string output_pattern);
  string interpolate(const boost::unordered_map<string, string> & field_values);
private:
  ...
};

我希望以这种方式在另一个类中使用Formatter

class A {
private:
  Format formatter;
public:
  A(const std::map<std::string, std::string> & info, ... other parameters) {
    std::map<std::string, std::string>::const_iterator it;
    it = info.find("format");
    if (it == info.end()) {
      throw std::runtime_error("Can't find 'format' in info");
    } else {
      formatter = Format(it->second);
    }
  }
};

如您所见,在调用构造函数之前还有一些工作要做。毫不奇怪,它不起作用,因为format首先使用默认构造函数(缺少)初始化,其次它期望为formatter = Format(it->second);行定义赋值运算符。

我无法像这样初始化formatter

A(const std::map<std::string, std::string> & info, ... other parameters):
  formatter(...) {
  ...
}

因为我首先要提取参数作为formatter初始化程序传递。

所以,最终我用这种方式解决了它:

class Format {
public:
  Format();
  void set_pattern(const string output_pattern);
  string interpolate(const boost::unordered_map<string, string> & field_values);
private:
  ...
};


class A {
private:
  Format formatter;
public:
  A(const std::map<std::string, std::string> & info, ... other parameters):
    formatter()
 {
    std::map<std::string, std::string>::const_iterator it;
    it = info.find("format");
    if (it == info.end()) {
      throw std::runtime_error("Can't find 'format' in info");
    } else {
      formatter.set_pattern(it->second);
    }
  }
};

我真的不喜欢这个,这使得不可变的formatter对象变成了可变的。这不是一个大问题。但是我不需要它是可变的,当我不得不让它变得可变时,因为我不能在代码中表达它是不可变的。

在我的情况下,我可以采用另一种好的方法在构造函数中初始化它吗?

1 个答案:

答案 0 :(得分:2)

您可以执行辅助私有功能来完成实际工作:

class A {
private:
  SomethingA before;
  Format formatter;
  SomethingB after;
public:
  A(const std::map<std::string, std::string>& info) :
    formatter(extractFormat(info))
  {
    // ...
  }
private:
  string extractFormat(const std::map<std::string, std::string>& info)
  {
    // Be careful here! The object is not constructed yet, you can't fully use it
    // this->before => ok
    // this->after => not ok
    // you could make this function static just to be safe
  }
};