2
 // Shadowing

 #include <iostream>
 using namespace std;
 const int MNAME = 30;
 const int M  = 13;

 class Person {   // Base Class
     char person[MNAME+1];
   public:
     void set(const char* n);
     void display(ostream&) const;
   protected:
     const char* name() const;
 };

 void Person::set(const char* n) {
     strncpy(person, n, MNAME);
     person[MNAME] = '\0';
 }

 void Person::display(ostream& os) const {
     os << person << ' ';
 }

 const char* Person::name() const { return person; }

 class Student : public Person { // Derived
     int no;
     char grade[M+1];
   public:
     Student();
     Student(int, const char*);
     void display(ostream&) const;
 };

 Student::Student() {
     no = 0;
     grade[0] = '\0';
 }

 Student::Student(int n, const char* g) {
     // see p.61 for validation logic
     no = n;
     strcpy(grade, g);
 }

 void Student::display(ostream& os) const {
     os << name() << ' '
        << no << << ' ' << grade << endl;
 }

 int main() {
     Person person;
     Student student(975, "ABBAD");

     student.set("Harry");
     student.display(cout); // Harry 975 ABBAD

     person.set("Jane Doe");
     person.display(cout); // Jane Doe
 }

display() への最初の呼び出し (学生に対して) は、display() の学生バージョンを呼び出します。display() への 2 回目の呼び出し (個人に対して) は、display() の Person バージョンを呼び出します。display() の派生バージョンは、学生オブジェクトのベース バージョンをシャドウします。基本バージョンは person オブジェクトで実行されます。

シャドーイングの意味がわかりません。両方のクラスに同じ表示関数が定義されていることを認識しています。明らかに、student.display と person.display を呼び出すと、それに応じてそれらが呼び出されます。では、これはどういう意味ですか:

display() の派生バージョンは、学生オブジェクトのベース バージョンをシャドウします。基本バージョンは person オブジェクトで実行されます。

シャドーイングがわかりません。

ソース: https://scs.senecac.on.ca/~btp200/pages/content/dfunc.html 継承 - 派生クラスの関数

4

3 に答える 3

2

クラスStudentは から継承しPersonます。これは、とりわけ、Studentオブジェクトが で定義されたすべての内部構造と で定義されたすべての内部構造から構成されてStudentいるPersonことStudentを意味しPersonます。つまり、オブジェクトには、基本クラスからのメソッドと派生クラスからのメソッドStudentの両方のバージョンが含まれます。displayシャドウイングとはdisplay、派生オブジェクトから を呼び出すときに派生クラス バージョンを呼び出し、基本クラス バージョンはそれによって "シャドウ" され、呼び出されないことを意味します。Student基本クラスの接頭辞: で明示的に指定することにより、シャドウ バージョンを内部から呼び出すことができますPerson::display。一般に、呼び出される関数はスコープ内で最も近い関数です。DerivedそれがスコープであるオブジェクトとDerived、外側のスコープ (base など) に存在する関数は影で覆われます。

于 2013-03-31T21:17:52.857 に答える
0

これは、おそらく a が欠落していることを意味しますvirtual

たとえば、 Person クラスはおそらく次のようになります。

 class Person {   // Base Class
     char person[MNAME+1];
   public:
     void set(const char* n);
     virtual void display(ostream&) const;
   protected:
     const char* name() const;
 };

現在、次のコードがある場合:

Person* student = new Student(975, "ABBAD")
student->set("Harry");
student->display(cout);

出力は「Harry 975 ABBAD\n」ではなく「Harry」になります。icepack が言うように、メッセージが表示される理由は、 Student クラスの display メソッドが Person クラスの display メソッドを「シャドウ」するためであり、そのメソッド virtual を宣言していないため、コンパイラはシャドウが偶発的であると想定します. 偶然ではない場合は、そのメソッドを仮想として宣言する必要があります。

于 2013-03-31T21:18:03.873 に答える
0

この小さな実験を試してみてください。次の関数を定義します。

void person_display(Person &p){
    p.display(cout);
}

次に、それを呼び出しmainます。personstudent

int main(){
   // [...]
   person_display(person);
   person_display(student);

}

どちらの場合も、メソッドPerson::displayが呼び出されることがわかります。シャドウイングは、その祖先クラスのメソッドのクラスでの再定義のために発生する現象です。インスタンスがサブクラスと見なされる限り、以前の定義をシャドウしますが、祖先と見なされるとすぐに、シャドウは消えます。

これは、virtual呼び出されるメソッドが常に実インスタンス クラスで定義されたメソッドであるメソッドとは対照的です。上記の実験Studentでは、単純なPerson.

于 2013-03-31T21:35:37.110 に答える