父子间的冲突(四十)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了父子间的冲突(四十)相关的知识,希望对你有一定的参考价值。

        我们学习了继承,那么现在就有一个问题了:子类中是否可以定义父类中的同名成员呢?如果可以,那么将如何区分?如果不可以,为什么呢?我们来用代码说明,看看是否支持

#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 = 10;
    
    return 0;
}

        我们在父类 Parent 中定义了一个成员变量 mi,在子类 Child 中也定义了成员变量 mi;那么我们直接对 c.mi 进行赋值操作,看看编译器能否识别?

技术分享图片

        经过编译,我们知道了编译器支持这样的写法,也就说,它知道此时我们赋值的是哪个 mi。在 C++ 中,其实子类是可以定义父类中的同名成员的,子类中的成员将隐藏父类中的同名成员。但父类中的同名成员依然存在于子类中,我们通过作用域分辨符(::)来访问父类中的同名成员。下来我们通过编程来看看怎样使用父类中被隐藏的同名成员。

#include <iostream>
#include <string>

using namespace std;

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

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

int main()
{
    Child c;
    
    c.mi = 10;
    c.Parent::mi = 100;
    
    cout << "c.mi = " << c.mi << endl;
    cout << "&c.mi = " << &c.mi << endl;
    
    cout << endl;
    
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
    cout << "&c.Parent::mi = " << &c.Parent::mi << endl;
    
    return 0;
}

        我们看到先打印两个类中定义的变量的地址,然后进行赋值,通过再次打印赋值操作的变量的地址来确定我们操作的到底是父类中的成员变量还是子类中的成员变量,编译结果如下

技术分享图片

        我们看到 c.mi 的地址和子类中的成变量的地址是一致的,而 c.Parent::mi 的地址和父类中的成员变量的地址是一致的。那么类中的成员函数是否可以进行重载呢?重载函数的本质为多个不同的函数,函数名和参数列表是唯一的标识,函数重载必须发生在同一个作用域中。那么子类中定义的函数是否能重载父类中的同名函数?我们还是以代码为例来进行分析

#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;
    
};

int main()
{
    Child c;
    
    c.mi = 10;
    c.Parent::mi = 100;
    
    cout << "c.mi = " << c.mi << endl;
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
    
    c.add(1);
    c.add(2, 3);
    
    cout << endl;
    
    cout << "c.mi = " << c.mi << endl;
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
    
    return 0;
}

        我们在父类中定义了两个 add 重载函数,那么我们在 main 函数中去使用,看看它会用在父类还是子类的成员变量中。

技术分享图片

        我们看到是父类中的成员变量使用 add 函数了。那么我们在子类中也定义 void add(int a, int b, int c) 函数呢?在 main 函数中添加 c.add(4, 5, 6);我们来看看编译结果

技术分享图片

        它报错了,没有可调用的函数,因为在这会发生同名覆盖。由此可见,子类中的函数无法重载父类中的成员函数,子类中的函数将隐藏父类中的同名函数。我们必须得使用作用域分辨符来访问父类中的同名函数,那么在子类中可以定义父类中完全相同的成员函数。我们试着加上作用分辨符(c.Parent::add(1);  c.Parent::add(2, 3);),再来编译下看看

技术分享图片

        我们看到已经编译通过,并且运行也是我们想要的效果。通过对父子关系的学习,总结如下:1、子类中可以定义父类中的同名成员;2、子类中的成员将隐藏父类中的同名成员;3、子类和父类中的函数不能构成重载关系;4、子类可以定义父类中完全相同的成员函数;5、使用作用域分辨符可以访问父类中的同名成员。


        欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083

以上是关于父子间的冲突(四十)的主要内容,如果未能解决你的问题,请参考以下文章

第47课 父子间的冲突

第47课 父子间的冲突

第47课 父子间的冲突

C++--继承中的构造与析构父子间的冲突

四十Django单元测试:PGSQL数据库配置常用测试工具DB冲突方案和代码覆盖率实战

7.QT-Qt对象间的父子关系