虚拟方法覆盖在C++
假设我们有一个叫做Vehicle
抽象类:虚拟方法覆盖在C++
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
变种的答案?
下将比赛一Bicycle
与Vehicle
:
Vehicle *aBicycle = new Bicycle(); Vehicle *aCar = new Car(); aBicycle->raceWith(aCar);
要使用Car
与Bicycle
竞赛,我们需要使用双派遣。
为了使双调度工作中,我们使用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);
}
这样做
Vehicle *aBicycle = new Bicycle();
aBicycle->raceWith(aCar);
类型阿卡尔是车辆(typeid(aCar).name()
),所以你的编译器调用与车辆的方法。
尝试
aBicycle->raceWith(static_cast<Car*>(aCar));
aBicycle->raceWith(dynamic_cast<Car*>(aCar));
至于为什么static_cast
或dynamic_cast
,你可以看看这个职位上的SO:Regular cast vs. static_cast vs. dynamic_cast
在那里抱歉,我错过了。 – Leviathlon
我曾说过**子类**。请不要将此作为答案。 – Leviathlon
在面向对象编程中它有一个定义。不幸的是,它永远不会有差异 – Leviathlon
试试这个,你可以使用动态转换来检测子类的类型。如果您保留virtual bool raceWith(Vehicle *anotherVehicle)
作为一种方法,可能virtual bool raceWith(Car *anotherVehicle)
和virtual bool raceWith(Bicycle *anotherVehicle)
将永远不会执行,因为anotherVehicle
是Vehicle类型的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;
}
我认为,为了实现您在此尝试的目标,Google -Visitor设计模式将帮助您更多 – JaNL
什么是双派遣? – Leviathlon
@Leviathlon双虚拟调度是根据** two **对象的动态类型调用正确实现的能力。 C++仅在'this'上提供单个虚拟调度。这里所描述的flatmouse被称为访问者模式,并且使用单次调度两次来实现双重调度。 – Quentin
这解决了这个问题。这样一个很好的答案。感谢您的关注。 – Leviathlon