【问题标题】:How to use Virtual Functions correctly [duplicate]如何正确使用虚拟功能 [重复]
【发布时间】:2019-07-28 00:10:50
【问题描述】:

我正在在一门课程中学习 c++ - 而我们只是在学习虚函数

我们有一个任务要创建一个基类:Car

和 3 个派生类:

  • 思域
  • 奥德赛
  • 法拉利

基类有一个 name 成员变量(带有 getter 和 setter)和一个返回默认值的 getDoorSpecs 函数

每个子类也有 getDoorSpecs,我们应该将它创建为一个虚函数。

我们提供了一个主函数作为我们不允许修改的驱动程序,我们必须创建一个函数 attachDoors() 可以接收每个子类的实例化 - 并使用正确的 getDoorSpecs 返回一个价值。

我以为我终于正确地创建了虚函数 - 但是当我运行它时,我显然不明白如何创建 attachDoors 函数以利用子类的虚函数。我想如果我调用基类,然后调用函数,它将被子类方法覆盖 - 但是虽然它编译得很好 - 它给我的输出并不完全正确。

这是我的代码:

#include <iostream>
#include <string>
using namespace std;

class Car
{
public:
   string name;

   Car() {
      name = "Unknown model";}

   string getName(){
      return name;}

   void setName(string iName){
      name = iName;}

   virtual string getDoorSpecs(){
      return "Unknown doors";}
};

class Civic   :   public Car
{
public:
   Civic(){
      name = "Civic";}

   virtual string getDoorSpecs() override{
      return "4 doors";}
};

class Odyssey   :   public Car
{
public:
   Odyssey(){
      name = "Odyssey";}

   virtual string getDoorSpecs() override{
      return "2 front doors, 2 sliding doors, 1 tail gate";}
};

class Ferrari   :   public Car
{
public:
   Ferrari(){
      name = "Ferrari";}

   virtual string getDoorSpecs() override{
      return "2 butterfly doors";}
};

/**********************************************************************
 * Function: attachDoors
 * Purpose: This function can accept any type of Car object. It will
 *  call the appropriate functions to display the name and the doors info.
 ***********************************************************************/

// TODO: Include your attachDoors function here
void attachDoors(Car iVehicle)
{
   cout << "Attaching doors to "
        << iVehicle.getName()
        << " - "
        << iVehicle.getDoorSpecs()
        << endl;
}

/**********************************************************************
 * Function: main
 * Purpose: This is the entry point and driver for the program.
 ***********************************************************************/
int main()
{
   // You should not change main

   Civic civic;
   Odyssey odyssey;
   Ferrari ferrari;

   attachDoors(civic);
   attachDoors(odyssey);
   attachDoors(ferrari);

   return 0;
}

这是它给出的输出:

Attaching doors to Civic - Unknown doors 
Attaching doors to Odyssey - Unknown doors 
Attaching doors to Ferrari - Unknown doors

这是我试图得到的输出:

Attaching doors to Civic - 4 doors
Attaching doors to Odyssey - 2 front doors, 2 sliding doors, 1 tail gate
Attaching doors to Ferrari - 2 butterfly doors 

根据我们被要求执行此操作的方式,我知道可能只需对该功能进行微小更改即可获得正确的输出:

void attachDoors(Car iVehicle)
{
   cout << "Attaching doors to "
        << iVehicle.getName()
        << " - "
        << iVehicle.getDoorSpecs()
        << endl;
}

但如果我能弄清楚我应该做什么,我会感到震惊。 (我已经在这里阅读了一些关于 SO 的答案 - 但没有一个点击给我我正在尝试的洞察力)

老实说,我真的觉得我在这门课程上很挣扎,但是当我能把事情做好时,我很享受它,而且很多时候我都能弄明白,只是这次显然不是。任何帮助都将不胜感激!

【问题讨论】:

  • 程序员的大部分时间都花在思考为什么事情不正常。

标签: c++


【解决方案1】:

您需要使用指针或对基类的引用来引用派生类对象。为该对象调用一个虚函数并执行该函数的派生类版本:

void attachDoors(Car& iVehicle)
{
   cout << "Attaching doors to "
        << iVehicle.getName()
        << " - "
        << iVehicle.getDoorSpecs()
        << endl;
}

另见:Why do virtual functions need to be passed with a pointer and not by value(of the object)?

【讨论】:

  • 是的!谢谢!我是如此接近!我什至认为这是一个指针的东西 - 并尝试使用 * 但当然没有骰子。它只需要通过引用 & 传递。你的回答太棒了谢谢!你不只是告诉我怎么做——而是帮助我理解原理!再次感谢!
  • @kiltannen 我很高兴它有帮助:)