2016-04-21 98 views
2

假设我们有一个叫做Vehicle抽象类:虚拟方法覆盖在C++

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

下将比赛一BicycleVehicle

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

aBicycle->raceWith(aCar); 

要使用CarBicycle竞赛,我们需要使用双派遣。

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

什么是双派遣? – Leviathlon

+1

@Leviathlon双虚拟调度是根据** two **对象的动态类型调用正确实现的能力。 C++仅在'this'上提供单个虚拟调度。这里所描述的flatmouse被称为访问者模式,并且使用单次调度两次来实现双重调度。 – Quentin

+0

这解决了这个问题。这样一个很好的答案。感谢您的关注。 – Leviathlon

1

这样做

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

类型阿卡尔是车辆(typeid(aCar).name()),所以你的编译器调用与车辆的方法。

尝试

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

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

+0

在那里抱歉,我错过了。 – Leviathlon

+0

我曾说过**子类**。请不要将此作为答案。 – Leviathlon

+0

在面向对象编程中它有一个定义。不幸的是,它永远不会有差异 – Leviathlon

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; 
} 
+0

我认为,为了实现您在此尝试的目标,Google -Visitor设计模式将帮助您更多 – JaNL