我有一个依赖于 printer
实例的类 messenger
。 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 的其余部分使用的是真实对象,而不是指针,并且在这里将指针作为参数会令人困惑/不一致。
在 C++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 中最好的方法是什么?有没有办法摆脱构造函数中完全不必要的拷贝?不幸的是,移动临时的在这里不起作用(对吧?)。
最佳答案
没有虚拟克隆方法就无法克隆多态对象。所以你可以:
- 传递并持有一个引用,并确保打印机在构建 messenger 的代码中的 messenger 之前没有被破坏,
- 传递并持有一个智能指针并使用 new 创建打印机实例,
- 传递一个引用并使用克隆方法在堆上创建打印机实例或
- 将实际类型的引用传递给模板,并在您仍然知道类型的情况下使用 new 创建实例。
最后是你对 C++0x std::unique_ptr
的建议,但在这种情况下,C++03 std::auto_ptr
将完全符合你的要求相同的服务(即您不需要移动它,否则它们是相同的)。
编辑:好的,嗯,还有一种方法:
- 使
printer
本身成为指向实际实现的智能指针。比它同时具有可复制性和多态性,但代价是一些复杂性。
关于c++ - 多态类成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6096916/