【问题标题】:c++ virtual class function returning instance of concrete subclassc++虚类函数返回具体子类的实例
【发布时间】:2019-10-07 15:44:06
【问题描述】:

我想要什么,如果不是用这种语法,但在精神上:

class A
{
   virtual A f()=0;
};

class B : public A
{
   B f();
};

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

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

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

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

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

注意:如果可能是 c++11,但也很想知道新版本的消息

【问题讨论】:

    标签: c++ inheritance virtual


    【解决方案1】:

    您尝试的解决方案存在对象切片的风险。将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 的完整界面。我不清楚这是否需要。如果是,您将需要一个额外的层。例如,定义一个返回 std::unique_ptr&lt;B&gt;g() f() 调用:

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

    【讨论】:

      【解决方案2】:

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

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

      Demo

      唯一的缺点是您不能让 B::f 返回 std::unique_ptr&lt;B&gt;,因为它与 std::unique_ptr&lt;A&gt; 不协变(即使它隐式转换为它)。

      【讨论】:

      • 您仍然可以使用协变 A* 和非协变 std::unique_ptr&lt;A&gt; 来获得预期的界面(可能使用 CRTP)。
      【解决方案3】:

      注意:如果可能是 c++11,但也很想知道新版本的消息

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

      如果基类中的返回类型为A&amp;,则在B中返回B&amp;即可。
      如果基类中的返回类型是A*,那么在B中返回B*就可以了。

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

      【讨论】:

        【解决方案4】:

        这样写

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-06-07
          • 2018-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多