基本派生类成员重写。挑战活动11.3

时间:2019-02-27 18:56:17

标签: c++

我要说的学校面临挑战

为类PetData定义一个成员函数PrintAll(),该函数按如下所示输出输出。提示:利用基类的PrintAll()函数。
名称:蓬松,年龄:5,ID:4444

然后,他们给我下面的代码,并提供了一个可以更改的小片段。之间 // FIXME:添加PrintAll()成员函数 和 / *您的解决方案在这里* / 是我添加的代码,但没有得到正确的结果。

我的代码

// FIXME: Add PrintAll() member function
   void PrintAll(){
      AnimalData data;
      data.PrintAll();
      cout << ", ID: " << idNum;
      }
   /* Your solution goes here  */

完整代码

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

class AnimalData {
public:
   void SetName(string givenName) {
      fullName = givenName;
   };
   void SetAge(int numYears) {
      ageYears = numYears;
   };
   // Other parts omitted

   void PrintAll() {
      cout << "Name: "  << fullName;
      cout << ", Age: " << ageYears;
   };

private:
   int    ageYears;
   string fullName;
};

class PetData: public AnimalData {
public:
   void SetID(int petID) {
      idNum = petID;
   };

   // FIXME: Add PrintAll() member function
   void PrintAll(){
      AnimalData data;
      data.PrintAll();
      cout << ", ID: " << idNum;
      }
   /* Your solution goes here  */

private:
   int idNum;
};

int main() {
   PetData userPet;

   userPet.SetName("Fluffy");
   userPet.SetAge (5);
   userPet.SetID  (4444);
   userPet.PrintAll();
   cout << endl;

   return 0;
}

我得到的结果
名称:,年龄:-502747520,ID:4444

我想要的结果
名称:蓬松,年龄:5,ID:4444

4 个答案:

答案 0 :(得分:3)

void PrintAll(){
    AnimalData data;
    data.PrintAll();
    cout << ", ID: " << idNum;
}

AnimalData data;创建一个默认初始化的新AnimalData,它与作为当前AnimalData一部分的PetData完全分开。由于您想使用已有的AnimalData,因此请舍弃此行,并从下一行删除data。这是可能会出错的地方,因此我将直接跳到正确的答案:要获得PrintData的{​​{1}}函数,您需要明确:

AnimalData

为什么不能简单地删除void PrintAll(){ AnimalData::PrintAll(); cout << ", ID: " << idNum; }

如果删除对象以在data上调用PrintAll

data
假定为

void PrintAll(){ PrintAll(); cout << ", ID: " << idNum; } thisthis,对于PetDataPetData函数的最佳匹配是当前函数。结果是无限recursion

在这里要学习的实际课程是在重用标识符时要小心。在这种情况下,PrintAll会遮盖PetData::PrintAll,并在AnimalData::PrintAll内部将其替换。该函数不是PetData,在这种情况下,您不需要virtual,因此不会覆盖。您可以通过函数和变量轻松,意外地执行此操作,从而导致程序正在使用哪个函数。

构建此程序的(可能)更好的方法

充分利用继承和多态性

virtual

答案 1 :(得分:1)

您似乎对如何在PetData中调用超类AnimalData的方法有一个小小的误解:

void PrintAll(){
      AnimalData data;
      data.PrintAll();
      cout << ", ID: " << idNum;
      }

这将创建类AnimalData的新实例,并在该对象上调用PrintAll()。因为fullName和ageYears不在此新对象中初始化,所以您会得到意外的输出。要调用超类的相同方法,语法为Superclass::Methodname()。因此,AnimalData::PrintAll()的正确版本如下:

void PrintAll(){
      AnimalData::PrintAll();
      cout << ", ID: " << idNum;
      }

答案 2 :(得分:1)

这是你的问题。

void PrintAll(){
  AnimalData data;
  data.PrintAll();
  cout << ", ID: " << idNum;
  }

此函数创建类AnimalData的新对象(将根据默认构造函数构造),然后在该对象上调用AnimalData::PrintAll方法。您想要做的就是在 this 对象上调用AnimalData::PrintAll方法。

void PrintAll(){
  AnimalData::PrintAll(); // call base class method
  cout << ", ID: " << idNum;
  }

答案 3 :(得分:0)

所以这个比我想象的要简单得多。确实是从PetData调用printAll方法,并附加ID num。

public void printAll(){
    super.printAll();
    System.out.print(", ID: " + idNum);
}