C++ 中的虚方法重写

Virtual method overrides in C++

假设我们有一个名为 Vehicle 的摘要 class:

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

我们有它的子classes BicycleCar:

//  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 变体的答案也很好吗?

通过

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

aCar 的类型是 Vehicle (typeid(aCar).name()),因此您的编译器使用 Vehicle 调用该方法。

尝试

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

至于为什么static_castdynamic_cast,你可以看看这个post上的SO:Regular cast vs. static_cast vs. dynamic_cast

以下将与 BicycleVehicle 比赛:

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

aBicycle->raceWith(aCar);

为了让 BicycleCar 比赛,我们需要使用双分派。

为了使双重调度工作,我们使用 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);
}

试试这个,你可以使用动态转换来检测子类的类型。如果将 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;
}