Я пытаюсь понять наследование и полиморфизм. Когда я запускаю это:
#include<iostream>
using namespace std;
class Base
{
int x;
public:
virtual Base* fun() = 0;
int getX() { return x; }
};
// This class inherits from Base and implements fun()
class Derived: public Base
{
public:
int y;
Derived* fun() {
Derived *d = new Derived;
d->y = 2;
return d;
}
};
int main(void)
{
Derived d;
Derived *p = d.fun();
cout<< p->y;
}
Это прекрасно работает, так как производный класс имеет право переопределять виртуальную функцию, используя другой тип возвращаемого значения, если тип возвращаемого значения является ковариантным с исходным типом возвращаемого значения.
Но что, если виртуальная функция содержит входной аргумент типа Base*
. Нравиться :
#include<iostream>
using namespace std;
class Base
{
int x;
public:
virtual Base* fun(Base * t) = 0;
int getX() { return x; }
};
// This class inherits from Base and implements fun()
class Derived: public Base
{
public:
int y;
Derived* fun(Derived *t) {
Derived *d = new Derived;
d->y = t->y;
return d;
}
};
int main(void)
{
Derived d;
Derived *p = d.fun();
cout<< p->y;
}
Это выдает ошибку error: invalid new-expression of abstract class type ‘Derived’ Derived *d = new Derived;
, которая, как я понимаю, означает, что компилятор не распознает реализацию виртуальной функции и рассматривает класс «Производный» как абстрактный.
Итак, как мы можем переопределить виртуальную функцию этого типа?? Я пытался найти его, но не нашел никакой ссылки. Если подобный вопрос существует, дайте мне знать. Спасибо
добавьте ключевое слово override
в метод, чтобы убедиться, что вы действительно переопределяете, а не перегружаете.
Спасибо @Yksisarvinen, теперь я понял, мы можем сохранить аргумент как Base*, но в основной функции мы можем передать Derived*.
Если бы мне это было нужно в моем собственном коде. Я бы написал новый производный класс следующим образом:
// This class inherits from Base and implements fun()
class Derived: public Base
{
public:
int y;
Derived* fun(Base *t) {
Derived *d = new Derived;
Derived* input = dynamic_cast<Derived *>(t);
ASSERT(input); // Cause the debug version to throw an exception so the error can be debugged
if (input)
d->y = t->y;
else
d->y = 0; // Or the default of your choice.
return d;
}
};
Это приводит к потенциальной ошибке времени выполнения, если переданный базовый тип не является правильным производным типом. Но я не вижу способа избежать этого.
Другие варианты, которые я вижу, это использование шаблонов. Где производный тип требует передачи производного типа. Или просто создайте новую функцию, которая принимает производный тип в качестве входных данных, а также переопределяет fun(Base *t)
;
using namespace std;
template <class T>
class Base
{
int x;
public:
virtual T* fun(T* t) = 0;
int getX() { return x; }
};
class Derived : public Base<Derived>
{
public:
int y;
Derived() { y = 0; }
Derived* fun(Derived* t) {
Derived *d = new Derived;
d->y = t->y;
return d;
}
};
int main(int argc, const char* argv[])
{
Derived *d = new Derived;
Derived * p = d->fun(d);
cout << p->y;
return 0;
}
тест в визуальной студии 2019.
Это невозможно. Вы должны переопределить с тем же именем функции и тем же количеством и типами аргументов.