У меня есть класс messenger
, который опирается на экземпляр printer
. printer
- это полиморфный базовый класс, и фактический объект передается messenger
в конструкторе.
Для неполиморфного объекта я бы просто сделал следующее:
class messenger {
public:
messenger(printer const& pp) : pp(pp) { }
void signal(std::string const& msg) {
pp.write(msg);
}
private:
printer pp;
};
Но когда printer
является полиморфным базовым классом, это больше не работает (нарезка).
Каков наилучший способ сделать эту работу, учитывая, что
- Я не хочу передавать указатель на конструктор и
- Класс
printer
не должен иметь виртуальный методclone
(= должен полагаться на построение копии).
Я не хочу передавать указатель на конструктор, потому что остальная часть API работает с реальными объектами, а не с указателями, и было бы непонятно, что здесь есть указатель в качестве аргумента.
В С++ 0x я мог бы использовать unique_ptr
вместе с конструктором шаблонов:
struct printer {
virtual void write(std::string const&) const = 0;
virtual ~printer() { } // Not actually necessary …
};
struct console_printer : public printer {
void write(std::string const& msg) const {
std::cout << msg << std::endl;
}
};
class messenger {
public:
template <typename TPrinter>
messenger(TPrinter const& pp) : pp(new TPrinter(pp)) { }
void signal(std::string const& msg) {
pp->write(msg);
}
private:
std::unique_ptr<printer> pp;
};
int main() {
messenger m((console_printer())); // Extra parens to prevent MVP.
m.signal("Hello");
}
Это лучшая альтернатива? Если да, то какой был бы лучший способ в pre-0x? И есть ли способ избавиться от совершенно ненужной копии в конструкторе? К сожалению, перемещение временного не работает здесь (правильно?).