• C++继承中的同名覆盖


    1,父子间的冲突是由继承带来的,两个类之间存在了继承的关系,必然的会带来一 些问题,本文要讨论的是父子之间成员变量或成员函数的命名问题;

     

    2,思考:

        1,子类中是否可以定义父类中的同名成员?

           1,可以,本文先编程解决这个问题;

           2,这个问题就是同名覆盖问题;

        2,如果可以,如何区分?如果不可以,为什么?

       

    3,同名成员变量编程实验:

     1 #include <iostream>
     2 #include <string>
     3 
     4 using namespace std;
     5 
     6 class Parent
     7 {
     8 public:
     9     int mi;
    10 };
    11 
    12 class Child : public Parent
    13 {
    14 public:
    15     int mi;  // 编译结果通过,子类可以定义父类里面的同名变量;
    16 };
    17 
    18 int main()
    19 {
    20     Child c;
    21     
    22     c.mi = 100;    // mi 究竟是子类自定义的,还是从父类继承得到的?
    23     
    24     return 0;
    25 }

       

    4,父子间的冲突(同名覆盖):

        1,子类可以定义父类中的同名成员;

        2,子类中的成员将隐藏父类中的同名成员;

           1,编译器认为已经从父类中继承得到这个成员了,又自定义了一个同名成员,目的只有一个,就是你想要自己自定义的同名成员、而不想要从父类那里继承得到的同名成员,因此会产生同名覆盖现象;

        3,父类中的同名成员依然存在于子类中;

           1,隐藏、不是销毁;

        4,通过作用域分辨符(::)访问父类中的同名成员;

       

    5,访问父类中的同名成员方式:

        1,Child c;

        2,c.mi = 100;  // 子类中的 mi;

        3,c.Parent::mi = 1000;  // 父类中的 mi;

       

    6,同名成员变量深度分析编程实验:

     1 #include <iostream>
     2 #include <string>
     3 
     4 using namespace std;
     5 
     6 namespace A
     7 {
     8     int g_i = 0;
     9 }
    10 
    11 namespace B
    12 {
    13     int g_i = 1;  // 同名的全局变量,但是位于两个不同的命名空间;
    14 }
    15 
    16 class Parent
    17 {
    18 public:
    19     int mi;
    20     
    21     Parent()
    22     {
    23         cout << "Parent() : " << "&mi = " << &mi << endl;
    24     }
    25 };
    26 
    27 class Child : public Parent
    28 {
    29 public:
    30     int mi;  // 编译器没有简单的对同名成员报错,是因为作用域,虽然两个成员的名字相同,但是出于不同的作用域当中;同命名空间的本质是一样的;
    31     
    32     Child()
    33     {
    34         cout << "Child() : " << "&mi = " << &mi << endl;
    35     }
    36 };
    37 
    38 int main()
    39 {
    40     Child c;  // Parent() : &mi = 0xbfb43a08    Child() : &mi = 0xbfb43a0c
    41     
    42     c.mi = 100;    
    43     
    44     c.Parent::mi = 1000;
    45     
    46     cout << "&c.mi = " << &c.mi << endl;  // &c.mi = 0xbfb43a0c,证明直接访问的是子类的 mi;  
    47     cout << "c.mi = " << c.mi << endl;  // c.mi = 100;
    48     
    49     cout << "&c.Parent::mi = " << &c.Parent::mi << endl;  // &c.Parent::mi = 0xbfb43a08;  作用域分辨符访问父类 mi;
    50     cout << "c.Parent::mi = " << c.Parent::mi << endl;  // c.Parent::mi = 1000;
    51     
    52     return 0;
    53 }

        1,父类和子类可以产生同名覆盖冲突,但是通过作用域分辨符可以解决这个问     题;

       

    7,再论重载:

        1,类中的成员函数可以进行重载:

           1,重载函数的本质为多个不同的函数;

           2,函数名和参数列表是唯一的标识;

           3,函数重载必须发生在同一个作用域中;

          

    8,问题:

        1,子类中定义的函数是否能重载父类中的同名函数?

           1,将父子间的冲突问题上升到成员函数了;

       

    9,父子间的函数重载编程实验:

        1,继承父类成员函数,累加父类的同名成员;

     1 #include <iostream>
     2 #include <string>
     3 
     4 using namespace std;
     5 
     6 class Parent
     7 {
     8 public:
     9     int mi;
    10     
    11     void add(int v)
    12     {
    13         mi += v;
    14     }
    15     
    16     void add(int a, int b)
    17     {
    18         mi += (a + b);
    19     }
    20 };
    21 
    22 class Child : public Parent
    23 {
    24 public:
    25     int mi;
    26 };
    27 
    28 int main()
    29 {
    30     Child c;
    31     
    32     c.mi = 100;    
    33     
    34     c.Parent::mi = 1000;
    35     
    36     cout << "c.mi = " << c.mi << endl;  // c.mi = 100;
    37     
    38     cout << "c.Parent::mi = " << c.Parent::mi << endl;  // c.Parent::mi = 1000;
    39     
    40     c.add(1);  // 继承自父类的成员函数;这个函数得到的 mi 不知道后面还要定义一个子类,它知道的 mi 只是父类中的,这个时候 mi 的作用域在父类中,所以给了父类中的 mi 做累加;
    41     c.add(2, 3);  // 继承自父类的成员函数;
    42     
    43     cout << "c.mi = " << c.mi << endl;  // c.mi = 100;
    44     
    45     cout << "c.Parent::mi = " << c.Parent::mi << endl;  // c.Parent::mi = 1006;累加到父类中的 mi 了;
    46     
    47     return 0;
    48 }

        2,函数的同名覆盖:

     1 #include <iostream>
     2 #include <string>
     3 
     4 using namespace std;
     5 
     6 class Parent
     7 {
     8 public:
     9     int mi;
    10     
    11     void add(int v)
    12     {
    13         mi += v;
    14     }
    15     
    16     void add(int a, int b)
    17     {
    18         mi += (a + b);
    19     }
    20 };
    21 
    22 class Child : public Parent
    23 {
    24 public:
    25     int mi;
    26     
    27     void add(int x, int y, int z)
    28     {
    29         mi += (x + y + z);
    30     }
    31 };
    32 
    33 int main()
    34 {
    35     Child c;
    36     
    37     c.mi = 100;    
    38     
    39     c.Parent::mi = 1000;
    40     
    41     cout << "c.mi = " << c.mi << endl;  // c.mi = 100;
    42     
    43     cout << "c.Parent::mi = " << c.Parent::mi << endl;  // c.Parent::mi = 1000;
    44     
    45     // c.add(1);  // 编译器显示没有匹配的函数调用 Child::add(int);同名成员函数覆盖,并没有重载,作用域不同;
    46     // c.add(2, 3);  // 编译器显示没有匹配的函数调用 Child::add(int, int);同名成员函数覆盖,并没有重载,作用域不同;
    47     
    48     c.Parent::add(1);  // 作用域分辨符解决同名成员函数覆盖问题;
    49     c.Parent::add(2, 3);  // 作用域分辨符解决同名成员函数覆盖问题;累加父类中的 mi
    50     
    51     c.add(4, 5, 6);  // 调用子类中的 add(),默认情况下访问的就是子类中的 mi,这个地方发生了同名覆盖;
    52     
    53     cout << "c.mi = " << c.mi << endl;  // c.mi = 115;默认访问的 mi 是子类中的 mi;
    54     
    55     cout << "c.Parent::mi = " << c.Parent::mi << endl;  // c.Parent::mi = 1006;前两次累加的是父类中的 mi;
    56     
    57     return 0;
    58 }

       

    10,父子间的冲突:

        1,子类中的函数将隐藏父类的同名函数;

        2,子类无法重载父类中的成员函数;

           1,因为它们处于不同的作用域;

        3,使用作用域分辨符访问父类中的同名函数;

           1,类名加上作用域分辨符;

        4,子类可以定义父类中完全相同的成员函数;

     1 #include <iostream>
     2 #include <string>
     3 
     4 using namespace std;
     5 
     6 class Parent
     7 {
     8 public:
     9     int mi;
    10     
    11     void add(int v)
    12     {
    13         mi += v;
    14     }
    15     
    16     void add(int a, int b)
    17     {
    18         mi += (a + b);
    19     }
    20 };
    21 
    22 class Child : public Parent
    23 {
    24 public:
    25     int mi;
    26     
    27     void add(int v)  // 同名覆盖;函数重写;
    28     {
    29         mi += v;
    30     }
    31     
    32     void add(int a, int b)  // 同名覆盖;函数重写;
    33     {
    34         mi += (a + b);
    35     }
    36     
    37     void add(int x, int y, int z)  // 重载;
    38     {
    39         mi += (x + y + z);
    40     }
    41 };
    42 
    43 int main()
    44 {
    45     Child c;
    46     
    47     c.mi = 100;    
    48     
    49     c.Parent::mi = 1000;
    50     
    51     cout << "c.mi = " << c.mi << endl;  // c.mi = 100;
    52     
    53     cout << "c.Parent::mi = " << c.Parent::mi << endl;  // c.Parent::mi = 1000;
    54     
    55     c.add(1);  // 同名覆盖;
    56     c.add(2, 3);  // 同名覆盖;
    57     c.add(4, 5, 6);  // 函数重载;
    58     
    59     cout << "c.mi = " << c.mi << endl;  // c.mi = 121;函数同名覆盖和重载,都是默认访问的子类的 mi;
    60     
    61     cout << "c.Parent::mi = " << c.Parent::mi << endl;  // 父类中的函数被同名覆盖,未有访问父类中的 mi;
    62     
    63     return 0;
    64 }

       

    11,小结:

        1,子类可以定义父类中的同名成员;

        2,子类中的成员将隐藏父类中的同名成员;

           1,包括同名成员变量和同名成员函数;

           2,重写的依据;

           3,这就是同名覆盖;

        3,子类和父类中的函数不能构成重载关系;

           1,作用域不同;

        4,子类可以定义父类中完全相同的成员函数;

           1,作用域不同;

        5,使用作用域分辨符访问父类中的同名成员;

           1,父类名加上作用域分辨符;

  • 相关阅读:
    动态规划(最长公共序列,最长上升序列)
    滴滴笔试--算术转移(20190827)
    线段树和树状数组
    pair和list学习
    数据结构--树(建立、遍历)
    tmux常用命令与快捷键
    机器学习实战-逻辑回归
    字符流中第一个重复的字符
    机器学习实战-朴素贝叶斯
    Python第三方库
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10915115.html
Copyright © 2020-2023  润新知