温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

父子间的冲突(四十)

发布时间:2020-03-30 23:43:52 来源:网络 阅读:488 作者:上帝之子521 栏目:编程语言

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

#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

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI