2013-11-29 4 views
1

Я написал класс для выполнения вывода данных, хранящихся в 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 объект в изменчивый. Здесь это не большая проблема. Но мне не нужно, чтобы он изменялся и мне не нравилось, когда мне нужно было изменить его только потому, что я не могу выразить его в коде, когда он неизменен.

Есть ли другой хороший подход, который я могу предпринять, чтобы инициализировать его в конструкторе в моем случае?

ответ

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 
    } 
}; 
Смежные вопросы