полиморфизм — переопределение виртуального метода в переполнении стека

Предположим, у нас есть абстрактный класс с именем Vehicle:

class Vehicle {
virtual bool raceWith(Vehicle *anotherVehicle) = 0;
};

И у нас есть свои подклассы Bicycle а также Car:

//  forward declaration
class Car;

class Bicycle : public Vehicle {
virtual bool raceWith(Vehicle *anotherVehicle) {
throw SomeExceptionClass();
}

virtual bool raceWith(Car *anotherVehicle) {
return true;
}

virtual bool raceWith(Bicycle *anotherVehicle) {
return false;
}
};

Тем не менее, этот блок кода вызывает SomeExceptionClass:

Vehicle *aBicycle = new Bicycle();
Vehicle *aCar = new Car();

aBicycle->raceWith(aCar);

Что тут делать? Разве C ++ не позволяет нам использовать полиморфные методы таким образом?

Любая помощь будет оценена. Благодарю.

РЕДАКТИРОВАТЬ: Будет также хорошо дать ответ dynamic_cast<> а также decltype варианты?

2

Решение

Следующее будет Bicycle с Vehicle:

Vehicle *aBicycle = new Bicycle();
Vehicle *aCar = new Car();

aBicycle->raceWith(aCar);

Участвовать в гонке Bicycle с Car нам нужно использовать двойную отправку.

Чтобы сделать двойную отправку, мы используем this указатель для вызова следующей функции, чтобы второй виртуальный вызов мог преобразоваться в правильный тип транспортного средства:

class Car;
class Bicycle;

class Vehicle {
public:
virtual bool raceWith(Vehicle& anotherVehicle) = 0;
virtual bool raceWith(Bicycle& anotherVehicle) = 0;
virtual bool raceWith(Car& anotherVehicle) = 0;
};class Bicycle : public Vehicle {
public:
virtual bool raceWith(Vehicle& anotherVehicle) override
{
//throw std::exception();
return anotherVehicle.raceWith(*this);
}

virtual bool raceWith(Car& anotherVehicle)
{
return true;
}

virtual bool raceWith(Bicycle& anotherVehicle)
{
return false;
}
};

class Car : public Vehicle {
public:
virtual bool raceWith(Vehicle& anotherVehicle) override
{
return true;
}

virtual bool raceWith(Car& anotherVehicle) override
{
return true;
}

virtual bool raceWith(Bicycle& anotherVehicle) override
{
return false;
}

};

int main()
{

Vehicle *aBicycle = new Bicycle();
Vehicle  *aCar = new Car();

aBicycle->raceWith(*aCar);
}

Обратите внимание return anotherVehicle.raceWith(*this); который выполнит второй виртуальный звонок.

Затем функции вызываются в следующем порядке:

  • main();
  • Bicycle::raceWith(Vehicle& anotherVehicle);
  • Car::raceWith(Bicycle& anotherVehicle);

Ниже приведена та же программа, но придерживающаяся использования указателей и исключений, как указано в вопросе:

#include <exception>

class Car;
class Bicycle;

class Vehicle {
public:
virtual bool raceWith(Vehicle* anotherVehicle) = 0;
virtual bool raceWith(Bicycle* bicycle) = 0;
virtual bool raceWith(Car* car) = 0;
};class Bicycle : public Vehicle {
public:
virtual bool raceWith(Vehicle* anotherVehicle) override
{
//throw std::exception();
return anotherVehicle->raceWith(this);
}

virtual bool raceWith(Car* car) override
{
return true;
}

virtual bool raceWith(Bicycle* bicycle) override
{
return false;
}
};

class Car : public Vehicle {
public:
virtual bool raceWith(Vehicle* anotherVehicle) override
{
throw std::exception();
}

virtual bool raceWith(Car* car) override
{
return true;
}

virtual bool raceWith(Bicycle* bicycle) override
{
return false;
}

};

int main()
{

Vehicle *aBicycle = new Bicycle();
Vehicle  *aCar = new Car();

aBicycle->raceWith(aCar);
}
4

Другие решения

При выполнении

Vehicle *aBicycle = new Bicycle();
aBicycle->raceWith(aCar);

Тип автомобиля — Автомобиль (typeid(aCar).name()), поэтому ваш компилятор вызывает метод с помощью Vehicle.

Пытаться

aBicycle->raceWith(static_cast<Car*>(aCar));
aBicycle->raceWith(dynamic_cast<Car*>(aCar));

Почему static_cast или же dynamic_castВы можете посмотреть этот пост на SO: Обычное приведение против static_cast против dynamic_cast

1

Попробуйте это, вы можете использовать динамическое приведение для определения типа для подкласса. Если вы продолжаете virtual bool raceWith(Vehicle *anotherVehicle) как метод, наверное virtual bool raceWith(Car *anotherVehicle) а также virtual bool raceWith(Bicycle *anotherVehicle) никогда не будет казнен без кастинга, так как anotherVehicle Тип транспортного средства obj. Надеюсь поможет 🙂

#include <iostream>
using namespace std;
class Car;
class Bicycle;

class Vehicle {
public:
//virtual bool raceWith(Vehicle *anotherVehicle) = 0;
virtual bool raceWith(Car *anotherVehicle) = 0;
virtual bool raceWith(Bicycle *anotherVehicle) = 0;
};

class Bicycle : public Vehicle {
/*virtual bool raceWith(Vehicle *anotherVehicle) {
throw SomeExceptionClass();
}*/
virtual bool raceWith(Car *anotherVehicle) {
cout << "will print" << endl;
return true;
}
virtual bool raceWith(Bicycle *anotherVehicle) {
return false;
}
};
class Car : public Vehicle {
/*virtual bool raceWith(Vehicle *anotherVehicle) {
throw SomeExceptionClass();
}*/
virtual bool raceWith(Car *anotherVehicle) {
return true;
}

virtual bool raceWith(Bicycle *anotherVehicle) {
return false;
}
};
int main()
{
Vehicle *aBicycle = new Bicycle();
Vehicle *aCar = new Car();

if (dynamic_cast<Bicycle*>(aCar) != NULL) {
std::cout << "Race with A Bicycle" << std::endl;
aBicycle->raceWith(static_cast<Bicycle*>(aCar));
}
else if (dynamic_cast<Car*>(aCar) != NULL) {
std::cout << "Race with A Car" << std::endl;
aBicycle->raceWith(static_cast<Car*>(aCar));
}
else {
//throw SomeExceptionClass();
}

//aBicycle->raceWith(aCar);

return 0;
}
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector