2015-01-15 140 views
4

我正面临以下问题。虚拟方法C++

我实现父类 - 车辆,它有一定的派生类,其中之一 - FastVehicle

在程序中我需要存储一个车辆向量*指针。指针也可能指向Vehicle对象或FastVehicle对象。

1)我想能够调用向量中的每个对象的方法print()。 的问题是,在FastVehicle的情况下,我也想一个参数转院的功能, 我需要调用与签名功能:

void print(int a) 

我知道虚函数机制一点点,但根据据我所知,它只在两个函数具有相同签名时才起作用。

我想听听有关如何解决问题的建议。

2)另外在派生类FastVehicle有一些独特的功能,它不会与父类Vehicle共享。 它执行的任务只应执行FastVehicle对象。 实现此目标的最简洁方法是什么? 我想,也许,以实现在父类车辆“空”虚函数和实施FastVehicle

的首要方法里面的“真实”的任务也许有人可以提出一个更好的解决方案。

谢谢

+0

可以实现通用接口或使用dynamic_cast。 –

+1

如果你真的希望派生类具有不兼容的接口,'dynamic_cast'就是答案。如果可以的话,定义一个通用接口将会更清洁。 –

+1

不得不使用'dynamic_cast'通常是一个你没有足够的想法。 – OMGtechy

回答

1

您可以随时使用dynamic_cast将Vehicle转换为FastVehicle。如果Vehicle不是FastVehicle,则返回NULL。这取决于你的使用情况,如果你真的应该这样做。

for(Vehicle* vehicle : vehicleVector) 
{ 
    FastVehicle* fastVehicle = dynamic_cast<FastVehicle*>(vehicle); 

    if(fastVehicle) 
    { 
     fastVehicle->print(1337); 
     fastVehicle->somethingElse(); 
    } 
    else 
    { 
     vehicle->print(); 
    } 
} 

完整的示例可在这里:https://ideone.com/69n6Jb

+0

谢谢你的回答。是否有必要让父类至少有一个虚函数来执行dynamic_cast? –

+1

@Day_Dreamer是的。 – Scintillo

+0

不要以为这会奏效。我认为dynamic_cast侧身(在兄弟姐妹之间)很好,所以你永远不会碰到其他人。 – ventsyv

0

也许你可以用一个抽象vehicleI重构:

struct vehicleI { 
    .... 
    virtual void print(int) = 0; 
} 

,然后你vehicle

struct vehicle : vehicleI { 
    .... 
    void print(int i = 0); 
} 

和你fastVehicle为:

struct fastvehicle: vehicleI { 
    .... 
    void print(int); 
} 
+1

请注意,如果您在'vehicleI'指针上调用print时不会使用'i = 0'默认参数,因为默认参数基于静态类型。就个人而言,我会完全避免默认参数以避免混淆。 –

+0

@ChrisDrew好点,应该是'printf'并接受可变数量的参数。或成为某种流... –

1

务实的解决方案是:

  1. 传递int a参数到虚拟print方法,但在Vehicle忽略它,只有当你建议用它FastVehicle

  2. ,只需添加一个“空的”虚函数到基类,它是一个无操作的Vehicle,只在FastVehicle

E.g:

struct Vehicle { 
    virtual ~Vehicle(){} 
    virtual void print(int /*a*/) const { std::cout << "Vehicle print\n"; } 
    virtual void somethingElse() { /* no-op */ } 
}; 

struct FastVehicle : Vehicle { 
    void print(int a) const override {std::cout << "FastVehicle print " << a << "\n";} 
    void somethingElse() override { std::cout << "Something else!\n"; } 
}; 

for (auto vehicle : vehicles) { 
    vehicle->print(512); 
    vehicle->somethingElse(); 
} 

Live demo

0

如果要正确使用动态调用到交通工具的接口,你需要定义一个通用的接口。 如果您需要在FastVehicle的情况下指定参数,但在FastVehicle的情况下不需要,那不再是一个接口。

有两种解决方法:

默认参数

struct Vehicle 
{ 
    virtual void print(int a=0) {}; 
}; 

struct FastVehicle : public Vehicle 
{ 
    void print(int a=0) override {}; 
}; 

现在你既可以带或不带参数调用。

第二个选项:

struct Vehicle 
{ 
    virtual void print() {}; 
}; 

struct FastVehicle : public Vehicle 
{ 
    void print() override {}; 
    void setA(int a) { _a = a; } 
    _a{}; 
}; 

现在,你可以通过其他方法来设置您的一个变量,而不是当您通过车辆的接口访问对象。

1

您很可能不得不重新考虑为什么您需要FastVehicle的参数,而不是其他类型的车辆。这对我来说是一个糟糕的设计。

只需在基类中声明print(int),重写它,但是在不需要int的类中,只需忽略它。