多态类成员变量

Kon*_*lph 13 c++ oop c++11

我有一个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;
};
Run Code Online (Sandbox Code Playgroud)

但是什么时候printer是多态基类,这不再起作用(切片).

考虑到这一点,做这项工作的最佳方法是什么

  1. 我不想传递指向构造函数的指针,并且
  2. printer类不应该需要一个虚拟的clone方法(=需要依靠拷贝构造).

我不想传递指向构造函数的指针,因为API的其余部分正在使用真实对象,而不是指针,并且在此处将指针作为参数会令人困惑/不一致.

在C++ 0x下,我或许可以使用a 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");
}
Run Code Online (Sandbox Code Playgroud)

这是最好的选择吗?如果是这样,那么在0x之前最好的方法是什么?有没有办法摆脱构造函数中完全不必要的副本?不幸的是,移动临时在这里不起作用(对吧?).

Jan*_*dec 9

没有虚拟克隆方法,无法克隆多态对象.所以你可以:

  • 传递并保持引用并确保打印机在代码构造信使中的信使之前没有被销毁,
  • 传递并按住智能指针并使用new创建打印机实例,
  • 使用clone方法或传递引用并在堆上创建打印机实例
  • 将对实际类型的引用传递给模板,并在仍然知道类型的同时使用new创建实例.

最后一个是你用C++ 0x建议的std::unique_ptr,但在这种情况下,C++ 03 std::auto_ptr会为你提供完全相同的服务(即你不需要移动它,否则它们是相同的).

编辑:好的,嗯,还有一个方法:

  • 使printer自己成为实际实现的智能指针.比它的可复制和多态同时以一些复杂性为代价.