虚方法C ++

时间:2015-01-15 20:40:55

标签: c++ inheritance virtual-functions

我面临以下问题。

我实现父类 - 车辆,它有一些派生类,其中一个 - FastVehicle

在程序中我需要存储一个Vector of Vehicle *指针。指针也可以指向Vehicle对象或FastVehicle对象。

1)我希望能够为向量中的每个对象调用方法 print()。 问题是,在FastVehicle的情况下,我也想将参数传递给函数, 我需要调用带签名的函数:

void print(int a)

我对虚函数机制有一点了解,但根据我的知识,它只有在两个函数具有相同的签名时才有效。

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

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

的重写方法中的任务

也许有人可以提出更好的解决方案。

感谢

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

务实的解决方案是:

  1. int a参数传递给虚拟print方法,但在Vehicle中将其忽略,仅在FastVehicle

  2. 中使用
  3. 如你所知,只需添加一个&#34;空&#34; Vehicle中无操作的基类的虚函数,仅在FastVehicle实现

  4. 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

答案 2 :(得分:1)

您很可能需要重新考虑为什么需要FastVehicle的参数,而不是其他任何类型的Vehicle。对我而言,这表明设计糟糕。

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

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

答案 4 :(得分:0)

如果要正确使用对Vehicle界面的动态调用,则需要定义公共接口。 如果你需要在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{};
};

现在您可以通过另一种方法设置'a'变量,但不能在通过Vehicle的界面访问对象时设置。