我有一个继承自父类的子类,但是孩子也会选择一个模板参数。这两个类都有一个'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提到的切片问题。
答案 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。
的返回类型中