这个问题相当于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
的实例,而不是子类的实例。
我当然可以在两个子类中编写两个版本的函数,但代码将是相同的,除了返回类型,因为要复制和修改的所有字段都在基类中。那么,还有其他选择吗?
答案 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 ++。