虚拟方法 C++

virtual methods C++

我遇到了以下问题。

我实现父 Class - Vehicle,它有一些派生的 classes,其中之一 - FastVehicle.

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

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

void print(int a)

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

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

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

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

谢谢

您始终可以使用 dynamic_cast 将 Vehicle 转换为 FastVehicle。如果 Vehicle 不是 FastVehicle,它 returns 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

也许你可以用抽象的方式重构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. int a参数传递给虚拟print方法但在Vehicle中忽略它,只在FastVehicle[=18=中使用它]

  2. 正如您所建议的,只需将 "empty" 虚函数添加到基 class 中,它在 Vehicle 中是一个空操作,并且仅在 FastVehicle

例如:

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

如果要正确使用对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 的接口访问该对象时则不能。

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

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