你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

C++——父子之间冲突

[复制链接]
gaosmile 发布时间:2020-8-23 22:22
一、父子之间的冲突:
1、思考
子类中是否可以定义父类中的同名成员?
如果可以的话,那么该怎样区分呢?
如果不可以的话,那么又是为啥呢?
代码实践:
#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;
};

class Child : public Parent
{
public:
    int mi;
};

int main()
{
    Child c;
   
    c.mi = 100;    // mi 究竟是子类自定义的,还是从父类继承得到的?
   
    return 0;
}
代码是否可以编译通过,我们来看一下编译器编译的结果:
root@txp-virtual-machine:/home/txp# g++ test.cpp
root@txp-virtual-machine:/home/txp#

什么情况,居然可以编译通过,但是你从肉眼看,你看出到底是父类mi还是子类的mi呢,显然我们不能够去瞎猜,那么接下来我们来学习里面的真理!
2、父子之间冲突的规则:
  • 子类可以定义父类中的同名成员
  • 子类中的成员将隐藏父类中的同名成员
  • 父类中的同名成员依然存在于子类中
  • 通过作用域分辨符(:访问父类中的同名成员,例如:

Child c;

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

c.Parent::mi = 1000; // 父类中的mi
代码实践:
#include <iostream>
#include <string>

using namespace std;

namespace A
{
    int g_i = 0;
}

namespace B
{
    int g_i = 1;// 同名的全局变量,但是位于两个不同的命名空间;
}

class Parent
{
public:
    int mi;
   
    Parent()
    {
        cout << "arent() : " << "&mi = " << &mi << endl;
    }
};

class Child : public Parent
{
public:
    int mi;
   
    Child()
    {
        cout << "Child() : " << "&mi = " << &mi << endl;
    }
};

int main()
{
    Child c;
   
    c.mi = 100;   
   
    c.Parent::mi = 1000;
   
    cout << "&c.mi = " << &c.mi << endl;
    cout << "c.mi = " << c.mi << endl;
   
    cout << "&c.Parent::mi = " << &c.Parent::mi << endl;
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
   
    return 0;
}
输出结果:
root@txp-virtual-machine:/home/txp# g++ test.cpp
root@txp-virtual-machine:/home/txp# ./a.out
Parent() : &mi = 0x7ffc270e7bf0
Child() : &mi = 0x7ffc270e7bf4
&c.mi = 0x7ffc270e7bf4
c.mi = 100
&c.Parent::mi = 0x7ffc270e7bf0
c.Parent::mi = 1000

3、回顾重载:
(1)类中的成员函数可以进行重载
  • 重载函数的本质为多个不同的函数
  • 函数名和参数列表是唯一的标识
  • 函数重载必须发生在同一个作用域中,这一点非常关键

(2)子类中定义的函数是否能够重载父类中的同名函数呢?
代码实践:
#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;
   
    void add(int v)
    {
        mi += v;
    }
   
    void add(int a, int b)
    {
        mi += (a + b);
    }
};

class Child : public Parent
{
public:
    int mi;
   
    void add(int v)
    {
        mi += v;
    }
   
    void add(int a, int b)
    {
        mi += (a + b);
    }
   
    void add(int x, int y, int z)
    {
        mi += (x + y + z);
    }
};

int main()
{
    Child c;
   
    c.mi = 100;   
   
    c.Parent::mi = 1000;
   
    cout << "c.mi = " << c.mi << endl;
   
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
   
    c.add(1);
    c.add(2, 3);
    c.add(4, 5, 6);
   
    cout << "c.mi = " << c.mi << endl;
   
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
   
    return 0;
}
结果输出:
root@txp-virtual-machine:/home/txp# g++ test.cpp
root@txp-virtual-machine:/home/txp# ./a.out
c.mi = 100
c.Parent::mi = 1000
c.mi = 121
c.Parent::mi = 1000

注解:从实验观察来看,函数重名和成员重名的作用一样,子类会覆盖父类的。
为了更加说明这点,我们再来看一个示例:
#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;
   
    void add(int v)
    {
        mi += v;
    }
   
    void add(int a, int b)
    {
        mi += (a + b);
    }
};

class Child : public Parent
{
public:
    int mi;
   
   
   
    void add(int x, int y, int z)
    {
        mi += (x + y + z);
    }
};

int main()
{
    Child c;
   
    c.mi = 100;   
   
    c.Parent::mi = 1000;
   
    cout << "c.mi = " << c.mi << endl;
   
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
   
    c.add(1);
    c.add(2, 3);
   c.add(4, 5, 6);
   
    cout << "c.mi = " << c.mi << endl;
   
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
   
    return 0;
}
编译结果:
root@txp-virtual-machine:/home/txp# g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:47:12: error: no matching function for call to ‘Child::add(int)’
     c.add(1);
            ^
test.cpp:47:12: note: candidate is:
test.cpp:29:10: note: void Child::add(int, int, int)
     void add(int x, int y, int z)
          ^
test.cpp:29:10: note:   candidate expects 3 arguments, 1 provided
test.cpp:48:15: error: no matching function for call to ‘Child::add(int, int)’
     c.add(2, 3);
               ^
test.cpp:48:15: note: candidate is:
test.cpp:29:10: note: void Child::add(int, int, int)
     void add(int x, int y, int z)
          ^
test.cpp:29:10: note:   candidate expects 3 arguments, 2 provided

注解:显示匹配不到add(int)和add(int,int)这两个函数
解决方案,就是利用作用域符分辨符解决问题:
#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;

    void add(int v)
    {
        mi += v;
    }

    void add(int a, int b)
    {
        mi += (a + b);
    }
};

class Child : public Parent
{
public:
    int mi;



    void add(int x, int y, int z)
    {
        mi += (x + y + z);
    }
};

int main()
{
    Child c;

    c.mi = 100;

    c.Parent::mi = 1000;

    cout << "c.mi = " << c.mi << endl;

    cout << "c.Parent::mi = " << c.Parent::mi << endl;
                                       c.Parent::add(1);
    c.Parent::add(2, 3);
   c.add(4, 5, 6);

    cout << "c.mi = " << c.mi << endl;

    cout << "c.Parent::mi = " << c.Parent::mi << endl;

    return 0;
}
                                                                                                   

输出结果:
root@txp-virtual-machine:/home/txp# ./a.out
c.mi = 100
c.Parent::mi = 1000
c.mi = 115
c.Parent::mi = 1006

4、小结:
  • 子类中的函数将隐藏父类的同名函数
  • 子类无法重载父类中的成员函数(不在同一作用域里面)
  • 使用作用域分辨符访问父类中的同名函数
  • 子类可以定义类中完全相同的成员函数

二、总结
  • 子类可以定义父类中的同名成员
  • 子类中的成员将隐藏父类中的同名成员
  • 子类和父类中的函数不能构造重载关系
  • 子类可以定义父类中完全相同的成员函数
  • 使用作用域分辨符访问父类中的同名成员或者函数

好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。

收藏 评论0 发布时间:2020-8-23 22:22

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版