模板化子类的无效协变返回类型

时间:2014-07-28 17:46:59

标签: c++ templates virtual covariance

我有一个继承自父类的子类,但是孩子也会选择一个模板参数。这两个类都有一个'clone'函数,只调用它们的复制构造函数。我想将副本设为虚拟,以便子类始终将其称为自己的副本。

以下是问题的简化版本:

#include <iostream>
using namespace std;

class Parent
{
public:
    virtual Parent foo() { cout << "Parent Foo\n"; return *this; }
};

template <class T>
class Child : public Parent
{
public:
    Child<T> foo() { cout << "Child Foo\n"; return *this; }
};

int main()
{
    Child<int> c;

    c.foo();

    return 0;
}

似乎Child类应该与Parent类协变。我错过了什么?有没有办法保持虚拟功能和模板?感谢。

修改

也许我之前的例子太简单了。这是一个扩展的简单示例:

#include <iostream>
using namespace std;

class Parent
{
public:
    Parent(){}
    virtual Parent clone() const { return Parent(*this); }
private:
    Parent( Parent const& cpy ) { };
};

template <class T>
class Child : public Parent
{
public:
    Child(){}
    Child<T> clone() const { return Child<T>(*this); }
private:
    Child( Child<T> const& cpy ) {};
};

int main()
{
    Child<int> c;
    Parent* pc = &c;
    pc->clone();

    return 0;
}

我希望通过复制虚拟副本来始终成为该类的实际副本。 我想避免返回指针,但看起来我将被迫返回指针以避免DieterLücking提到的切片问题。

1 个答案:

答案 0 :(得分:6)

父母和孩子的类型不是协变的,但是父母和子女。和儿童&amp;是

#include <iostream>
using namespace std;

class Parent
{
public:
    virtual Parent& foo() = 0;
};

template <class T>
class Child : public Parent
{
public:
    Child& foo() { cout << "Child Foo\n"; return *this; }
};

int main()
{
    Child<int> c;
    Parent& parent = c.foo();
    return 0;
}

来自10.3.7虚拟功能

  

覆盖函数的返回类型应与...相同   被重写函数的返回类型或与变量的协变   功能的类。如果函数D :: f覆盖函数   B :: f,函数的返回类型如果满足则是协变的   以下标准:

     

- 两者都是指向类的指针,两者都是   左值对类的引用,或两者都是对它的右值引用   classes112

     

- B :: f的返回类型中的类与   返回类型为D :: f的类,或者是明确的和   返回中类的可访问直接或间接基类   D :: f

的类型      

- 指针或引用都有相同的含义   cv-qualification和D :: f的返回类型中的类类型有   与类类型相同的cv资格或更少的cv资格   在B :: f。

的返回类型中