简体   繁体   English

C ++继承相同类型签名的成员函数(阴影)

[英]C++ inheriting member functions of the same type signature (shadowing)

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

The first call to display() (on student) calls the Student version of display(). 对display()的首次调用(在学生身上)将调用Student版本的display()。 The second call to display() (on person) calls the Person version of display(). 对person的display()的第二次调用将调用display()的Person版本。 The derived version of display() shadows the base version on the student object. display()的派生版本遮盖了学生对象的基本版本。 The base version executes on the person object. 基本版本在person对象上执行。

I don't understand what shadowing is then. 我不明白那是什么阴影。 I realize that both classes have the same display function defined, and obviously if you call student.display and person.display its going to call them accordingly. 我意识到这两个类都定义了相同的显示函数,并且很明显,如果您调用Student.display和person.display它将相应地调用它们。 So what does this mean: 那么这是什么意思:

The derived version of display() shadows the base version on the student object. display()的派生版本遮盖了学生对象的基本版本。 The base version executes on the person object. 基本版本在person对象上执行。

I don't understand shadowing. 我不明白阴影。

source: https://scs.senecac.on.ca/~btp200/pages/content/dfunc.html Inheritance - Functions of a derived class 来源: https : //scs.senecac.on.ca/~btp200/pages/content/dfunc.html继承-派生类的功能

Your Student class inherits from Person . 您的Student类继承自Person That means, among other things, that Student objects consist from all the internals defined in Student and from all the internals defined in Person - for this matter Student can be seen as containing the Person . 这意味着,除其他事项外, Student对象来自定义的所有内部由Student和来自定义的所有内部Person -这件事Student可以看作是含有Person This means that Student object contains both versions of display method - one from the the base class and one from the derived. 这意味着Student对象包含display方法的两个版本-一个来自基类,另一个来自派生类。 Shadowing means that when invoking the display from the derived object, it will call the derived class version, and the base class version is "shadowed" by it and not called. 阴影表示从派生的对象调用display时,它将调用派生的类版本,基类版本被其“阴影化”而不被调用。 You can call the shadowed version from within Student by explicitly specifying it with base class prefix: Person::display . 您可以在Student调用带阴影的版本,方法是使用基类前缀Person::display明确指定它。 In general, the function that will be called is the one closest in scope - for Derived objects it's the scope of Derived and functions residing in outer scopes (such as base) are shadowed away. 一般情况下,将被调用的函数的范围是最接近的一员- Derived对象它的范围Derived和居住在外部范围(如碱)功能被遮蔽了。

It means that you're most likely missing a virtual . 这意味着您很可能会丢失virtual

Eg, your Person class should probably look like: 例如,您的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;
 };

Right now, if you have the following code: 现在,如果您具有以下代码:

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

Your output will be "Harry " instead of "Harry 975 ABBAD\\n". 您的输出将是“ Harry”,而不是“ Harry 975 ABBAD \\ n”。 As icepack says, the reason you're getting the message is because the display method in the Student class "shadows" the display method in the Person class, and because you have not declared that method virtual, the compiler assumes that the shadowing is accidental. 正如icepack所说,收到消息的原因是因为Student类中的显示方法“遮盖了” Person类中的显示方法,并且由于您尚未将该方法声明为虚拟方法,因此编译器认为阴影是偶然的。 If it's not accidental, then you should declare that method virtual. 如果不是偶然的,那么您应该将该方法声明为virtual。

Try this little experiment. 试试这个小实验。 Define the following function: 定义以下功能:

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

Then have main call it on person and student . 然后让main称之为对personstudent

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

}

You will see that in both cases, the method Person::display will be called. 您将看到,在两种情况下,都会调用Person::display方法。 The shadowing is a phenomenom happening because of the redefinition in a class of a method of its ancestor class. 由于在其祖先类的方法的类中进行了重新定义,因此出现阴影是现象。 It shadows the previous definition, as long as the instance is considered as the subclass, but as soon as it is seen as the ancestor, the shadowing disappears. 只要实例被视为子类,它就会遮盖先前的定义,但是一旦将其视为祖先,则阴影就会消失。

This is in contrast with a virtual method, where the method called is always the one defined in the real instance class, ie. 这与virtual方法相反,在virtual方法中,被调用的方法始终是在实实例类中定义的方法。 in the experiment described above, you would see the Student method being called, even though it is seen as a simple Person . 在上述实验中,即使您将Student方法视为简单的Person ,也将看到它被调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM