У меня есть дочерний класс, который наследуется от родительского класса, но дочерний класс также получает аргумент шаблона. Оба класса имеют функцию «клон», которая просто вызывает их конструктор копирования. Я хочу сделать копию виртуальной, чтобы дочерний класс всегда вызывал свою собственную копию.
Вот упрощенная версия проблемы:
#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;
}
Я хотел бы, чтобы копия всегда была реальной копией класса, делая копию виртуальной.
Я хотел избежать возврата указателя, но похоже, что я буду вынужден возвращать указатели, чтобы избежать проблемы срезов, упомянутой Дитером Люкингом.
Типы Parent и Child являются не ковариантными, а Parent.& и ребенок& являются.
#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, возвращаемые типы функций ковариантны, если они удовлетворяют
следующие критерии:— оба указатели на классы, оба
lvalue ссылки на классы, или оба являются rvalue ссылками на
classes112— класс в возвращаемом типе B :: f является тем же классом, что и
класс в возвращаемом типе D :: F, или является однозначным и
доступный прямой или косвенный базовый класс класса в возвращении
тип D :: f— оба указателя или ссылки имеют одинаковые
cv-квалификация и тип класса в возвращаемом типе D :: f имеет
та же квалификация cv или меньше квалификации cv, чем у типа класса
в возвращаемом типе B :: f.