C ++中的虚方法覆盖

时间:2016-04-21 18:18:08

标签: c++ polymorphism virtual-method dynamic-dispatch

假设我们有一个名为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变体的答案也很好吗?

3 个答案:

答案 0 :(得分:4)

以下内容将使用Bicycle

Vehicle进行竞争
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);
}

答案 1 :(得分: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_castdynamic_cast,你可以在SO上查看这篇文章:Regular cast vs. static_cast vs. dynamic_cast

答案 2 :(得分: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;
}