返回子类实例的超类中的方法

时间:2015-09-16 13:00:42

标签: c++ templates inheritance

这个问题相当于Java How to make Superclass Method returns instance of SubClass

假设这个类层次结构:

class A
{
    public:
        A makeCopyOfObject();
};
class B: public A
{
    public:
        void doSomethingB();
};
class C: public A
{
    public:
        void doSomethingC();
};

我想以这种方式使用它:

B().makeCopyOfObject().doSomethingB();
C().makeCopyOfObject().doSomethingC();

但当然我不能,因为makeCopyOfObject函数返回A的实例,而不是子类的实例。

我当然可以在两个子类中编写两个版本的函数,但代码将是相同的,除了返回类型,因为要复制和修改的所有字段都在基类中。那么,还有其他选择吗?

3 个答案:

答案 0 :(得分:2)

我不明白你试图用它做什么,它可能不是一个答案(见评论),但你可以做的是一个模板(详见Curiously recurring template pattern)。

template<typename CRTP>
class A {
public:
    CRTP& makeCopyOfObject() {
        return static_cast<CRTP&>(*this);
    }
};

class B: public A<B> {
public:
    void doSomethingB();
};

class C: public A<C> {
public:
    void doSomethingC();
};

并按照您的意愿使用它:

b.makeCopyOfObject().doSomethingB();
c.makeCopyOfObject().doSomethingC();

请参阅运行示例here

<强>旁注: 由于懒惰,即使函数被称为makeCopyOfObject,它也会创建副本,但会返回对该对象的引用。要执行复制,您必须实现复制构造函数并返回副本(搜索克隆模式)。

答案 1 :(得分:1)

很难看到任何实际用例,但使用非成员函数模板很容易:

template< class Type >
auto copy_of( Type const& o )
    -> Type
{ return o; }

然后你可以写

copy_of( B() ).doSomething();

到你心中的内容,而不仅仅是写作

B().doSomething();

享受。

对于协变方法的学术问题,有很多要说的。您可以查看如何实现clone方法的答案。本质上,除了类型系统支持引用或指针结果之外,C ++不支持这一点,因此必须“手动”执行,并且三种常见方法是(1)在每个类中完全手动实现,(2)使用宏扩展到每个类中的必要代码,以及(3)将参数转发给基类构造函数的中间类。对于C ++ 03,第三种方式与在虚拟继承层次结构中利用优势一样具有相同的难度,因此使用C ++ 03也是一个可供选择的选项。但它与C ++ 11及更高版本,(1),(2)和(3)的实用性并不合适。

答案 2 :(得分:0)

首先,要小心slicing

其次,如果你想制作一个对象的副本,我可以建议 复制构造函数:

B b1{};
B b2{b1}.doSomethingB();

甚至:

B{ B{} }.doSomethingB();

此外,如果您想保留多态行为,请始终 通过smart-pointers或引用来处理多态类。

请注意,C ++具有value-semantics,而Java具有引用语义,因此适用于Java的设计模式不一定适合C ++。