基本派生的类成员覆盖.挑战活动11.3

Basic derived class member override. Challenge Activity 11.3

本文关键字:挑战 活动 覆盖 成员 派生      更新时间:2023-10-16

我对学校的挑战

class PetData定义成员函数PrintAll(),该成员函数按以下方式打印输出。提示:利用基类的PrintAll()功能。
名称:蓬松,年龄:5,ID:4444

然后,他们将我可以更改的小片段给我下面的代码。之间 // FIXME: Add PrintAll()成员功能和 /* Your solution goes here */是我添加的代码,但我没有得到正确的结果。

mycode

// 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

in

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

AnimalData data;创建了一个新的默认限制AnimalData,该CC_7与当前PetData的一部分完全分开。由于您想使用已经拥有的AnimalData,请丢弃此行,然后从下一行中删除data。这是事情可能会出错的地方,因此我将直接跳过正确的答案:要获得PrintData的CC_12函数,您需要明确:

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

为什么您不能简单地删除data

如果删除对象调用PrintAll,则data

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

thisthisPetData,对于PetDataPrintAll功能的最佳匹配是当前功能。结果是无限递归。

在这里重新使用标识符时要小心要学会的真正教训。在这种情况下,PetData::PrintAll阴影AnimalData::PrintAll,在PetData中替换它。该功能不是virtual,在这种情况下,您不需要virtual,因此您不会获得覆盖。您可以轻松而意外地使用功能和变量来执行此操作,从而使程序使用哪一个。

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

利用继承和多态性

#include <iostream>
#include <string>
using namespace std;
class AnimalData
{
public:
    virtual ~AnimalData() {}; // with polymorphism you must make sure the 
                              // correct destructor is always called.
                              // Derived classes will override this 
                              // destructor whether you explicitly define 
                              // them or not. 
    void SetName(string givenName)
    {
        fullName = givenName;
    }
    void SetAge(int numYears)
    {
        ageYears = numYears;
    }
    // virtual function. Derived classes can, but do not have to, replace 
    // this function with a version better suited to the derived class
    virtual void PrintAll()
    {
        cout << "Name: " << fullName;
        cout << ", Age: " << ageYears;
    }
private:
    int ageYears;
    string fullName;
};
class PetData: public AnimalData
{
public:
    void SetID(int petID)
    {
        idNum = petID;
    }
    // Replacing virtual function. Note if the base class function is 
    // virtual, then child class overrides are automatically virtual
    void PrintAll() override // override keyword notifies with a compiler 
                             // error if the function does NOT override when 
                             // it should.
    {
        AnimalData::PrintAll(); // call base class version for basic data
        cout << ", ID: " << idNum; // adding derived class-specific stuff
    }
private:
    int idNum;
};
// can add WildData here to handle wild animals.
int main()
{
    PetData userPet;
    userPet.SetName("Fluffy");
    userPet.SetAge(5);
    userPet.SetID(4444);
    userPet.PrintAll();
    cout << endl;
    // add an vanilla animal for demo
    AnimalData generic;
    generic.SetName("Fang");
    generic.SetAge(7);
    generic.PrintAll();
    cout << endl;
    // demonstrate polymorphism
    AnimalData * ptr = & generic;
    ptr->PrintAll();
    cout << endl;
    ptr = & userPet;
    ptr->PrintAll(); // runtime calls the correct PrintAll function
    cout << endl;
    return 0;
}

您似乎对如何调用petdata中的超类动物的方法有一个小小的误解:

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

这创建了类动物数据的新实例,并在该对象上调用printall()。因为在这个新对象中没有初始化的fullname和apeyears,因此您会获得意外的输出。为了调用相同的超类方法,语法为 Superclass::Methodname()。因此,AnimalData::PrintAll()的正确版本如下:

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

这是您的问题。

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

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

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

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

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