2

假设我们有一个名为的抽象类Vehicle

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

我们有它的子类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变体也很好?

4

3 回答 3

4

The following will race a Bicycle with a Vehicle:

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

aBicycle->raceWith(aCar);

To race a Bicycle with a Car we need to use double dispatch.

To make double dispatch work we use the this pointer to call the next function so that the second virtual call can resolve to the correct type of vehicle:

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);
}

Note the return anotherVehicle.raceWith(*this); which will perform the second virtual call.

The functions are then called in this order:

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

The following is the same program, but sticking with the use of pointers and exceptions as provided in the question:

#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);
}
于 2016-04-21T18:30:56.173 回答
1

试试这个,你可以使用动态转换来检测子类的类型。如果您保留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;
}
于 2016-04-21T19:29:06.903 回答
1

通过做

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_cast或者dynamic_cast,你可以看一下SO上的这个帖子:Regular cast vs. static_cast vs. dynamic_cast

于 2016-04-21T18:19:56.883 回答