返回具体子类实例的 C++ 虚拟类函数

c++ virtual class function returning instance of concrete subclass

本文关键字:C++ 虚拟 类函数 实例 子类 返回      更新时间:2023-10-16

我想要什么,如果不使用此语法,而是在精神上:

class A
{
virtual A f()=0;
};
class B : public A
{
B f();
};

我确实看到了上面代码的问题:A 是虚拟的,因此无法创建 A 的实例,因此无法返回 A 的实例。

然而,A 的具体子类(例如 B(必须实现函数 f,它总是能够返回 themselve 的实例(例如 B 的实例(,即 A 子类的实例。

虽然上述内容不正确且无法编译,但有没有办法获得类似有效的东西? 可能,但不一定,类似

class A 
{
virtual "a concrete sublclass of A" f()=0;
};

注意:我不想返回指针或引用,因为我不希望 B 将自身的实例作为属性进行管理。

注意:如果可能的话,C ++ 11,但也很好奇听到更新的版本

您尝试的解决方案存在对象切片的风险。将B复制为A可能无法按预期方式工作。通常,在处理多态类型时最好避免使用值语义。考虑改为返回std::unique_ptr<A>

#include <memory>
class A
{
public:
virtual std::unique_ptr<A> f()=0;
};
class B : public A
{
public:
std::unique_ptr<A> f() override;
};

这需要C++11。它将按照预期的方式运行,用户不必管理结果对象的生存期。

但是,与原始代码中显示的相反,B::foo()不会让您访问B的完整界面。我不清楚这是否是必需的。如果是,您将需要一个额外的层。例如,定义一个返回f()调用的std::unique_ptr<B>g()

class B : public A
{
public:
std::unique_ptr<A> f() override { return g(); }
std::unique_ptr<B> g();
};

看起来您正在尝试编写各种工厂或克隆函数。这通常使用std::unique_ptr将创建对象的所有权干净地传递给调用方来完成:

class A
{
virtual std::unique_ptr<A> f() = 0;
};
class B : public A
{
std::unique_ptr<A> f() override;
};

演示

唯一的缺点是你不能B::f返回一个std::unique_ptr<B>,因为它与std::unique_ptr<A>不协变(即使它隐式转换为它(。

注意

:如果可能的话,C ++ 11,但也很好奇听到更新的版本

不,这是不可能的。不过,您可以在派生类中返回协变类型。

如果基类中的返回类型是A&,则可以在B中返回B&
如果基类中的返回类型是A*,则可以在B中返回B*

class A
{
virtual A& f()=0;
virtual A* g()=0;
};
class B : public A
{
B& f();
B* g()=0;
};

写类似的东西

class A
{
virtual const A& f() const = 0;
};
class B : public A
{
const B& f() const override { return *this; }
};

您可以使用指针代替引用。