【问题标题】:How to return a templated derived class instead of base class in an overridden function?如何在重写函数中返回模板派生类而不是基类?
【发布时间】:2020-04-17 14:50:05
【问题描述】:
#include <iostream>

template <typename T>
class A {};

template <typename T>
class B : public A<T> {};

class C
{
    virtual A<int> func() = 0;
};

class D : public C
{
    virtual B<int> func() override
    {
        return B<int>{};
    }
};

这里B 继承自A,模板参数是int 用于两个返回值。为什么我不能只返回B&lt;int&gt; 而不是A&lt;int&gt;

【问题讨论】:

    标签: c++ templates inheritance return-type


    【解决方案1】:

    正如 merlinND 所指出的,您必须从 class A&lt;T&gt; 继承。但它仍然会失败,除非您返回一个指针或对 B 的引用而不是值类型。以下将编译。

    #include <iostream>
    
    template <typename T>
    class A {};
    
    template <typename T>
    class B : public A<T> {};
    
    class C
    {
        virtual A<int>* func() = 0;
    };
    
    class D : public C
    {
        virtual B<int>* func() override
        {
            return new B<int>{};
        }
    };
    

    【讨论】:

      【解决方案2】:

      当声明 B 时,你必须继承一个实际的类,而不是一个模板:

      template <typename T>
      class B : public A<T> {};
      

      第二个问题是在类D 中覆盖func() 的签名时不能更改它。但是,一旦解决此问题,您将能够按预期返回 B&lt;int&gt;{}

      编辑:@Josh Wilson 指出的第三个问题是,您不会从 func() 的返回值中获得 B 的行为,因为它指定了按值返回的 A。您需要返回一个指向 A&lt;int&gt; 的指针以应用多态性。

      【讨论】:

      • 那是个错误。我改变了它。谢谢。
      【解决方案3】:

      B D::func() 不能覆盖 AC::func(),因为这两个函数的返回类型彼此不同。

      【讨论】:

        【解决方案4】:

        来自cppreference

        如果函数 Derived::f 覆盖函数 Base::f,则它们的返回类型必须相同或协变。

        两种类型协变需要满足三个条件,其中之一是它们需要是指针类型或引用类型。

        A&lt;int&gt;B&lt;int&gt; 既不是同一类型也不是协变类型,这意味着您不能使用 B&lt;int&gt; 作为被覆盖方法的返回类型。

        还请注意,您不必在被覆盖的方法中使用 virtual 说明符。

        此外,正如其他人所注意到的,以下将起作用并返回一个A&lt;int&gt;-typed 对象:

        A<int> func() override
        {
            return B<int>{};
        }
        

        但你应该避免它。事实上,在创建B&lt;int&gt; 对象后,它会切片A&lt;int&gt; 类型,原因我们已经看到,这意味着您的对象类型实际上只是A&lt;int&gt;,并且不是B&lt;int&gt; 的实例。这意味着当您本可以创建 A&lt;int&gt; 时,您徒劳地创建了 B&lt;int&gt; 实例。

        如果您需要B&lt;int&gt;,则需要返回指针或引用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-03-19
          • 1970-01-01
          • 2014-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多