继承中的访问级别(三十七)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了继承中的访问级别(三十七)相关的知识,希望对你有一定的参考价值。

        我们在上篇博客中介绍了 C++ 中的继承,那么我们想想既然是继承了,子类是否可以直接访问父类中的私有成员呢?根据面向对象理论子类拥有父类的一切属性和行为,自然子类也就能直接访问父类的私有成员!但是根据 C++ 语法外界不能直接访问类的 private 成员,因此子类就不能直接访问父类的私有成员!那么到底哪种是正确的呢?我们来编程实验下

#include <iostream>
#include <string>

using namespace std;

class Parent
{
    int mv;
public:
    Parent()
    {
        mv = 100;
    }
    
    int value()
    {
        return mv;
    }
};

class Child : public Parent
{
public:
    int addValue(int v)
    {
        mv = mv + v;
    }
};

int main()
{
    
    return 0;
}

        我们来编译下看看是否可以通过

技术分享图片

        编译报错了,说明我们的第二种分析是正确的。那么不是说继承可以获得父类的全部资源嘛,它的私有成员在子类中就不能被访问。接下来我们就要介绍一个概念了,在面向对象中的访问级别不只是 public 和 private,还有个 protected 访问级别。那么 protected 关键字的意义是什么呢?被它修饰的成员不能被外界直接访问,但是它修饰的成员可以被子类直接访问。接下来我们体验下 protected 。

#include <iostream>
#include <string>

using namespace std;

class Parent
{
protected:
    int mv;
public:
    Parent()
    {
        mv = 100;
    }
    
    int value()
    {
        return mv;
    }
};

class Child : public Parent
{
public:
    int addValue(int v)
    {
        mv = mv + v;
    }
};

int main()
{
    Parent p;
    
    cout << "p.mv = " << p.value() << endl;
    
    Child c;
    
    cout << "c.mv = " << c.value() << endl;
    
    c.addValue(50);
    
    cout << "c.mv = " << c.value() << endl;
    
    return 0;
}

        我们来试下将 private 属性换成 protected,看看编译可以通过吗?

技术分享图片

        我们看到编译通过了,也正常运行了。那么我们在 main 函数中直接给 p.mv 和 c.mv 赋值为 1000 呢?我们看看编译结果

技术分享图片

        我们看到编译失败了,因为成员变量 mv 是 protected 的,所以在外界不能直接访问。那么为什么在面向对象中需要 protected 呢?我们来想想现实生活中,比如小明要去医院看病。有些隐秘的病史,小明肯定不想让别人知道,但是这时必须得给医生坦白,不然没法治病哈。这时便有了 protected 这个需求了,这个病史不是纯私有的,但又不是暴露在大众之下的。我们面向对象的思想中,为了更完美的贴合生活,便有了 protected 这个关键字。那么我们在定义类时访问级别是怎样选择的呢?我们来看看下面这张表。注:表是由唐长老总结出来的!

技术分享图片

        关系已经很明确了,我就不多废话了。下来我们来看个示例,关系如下

技术分享图片

        用程序描述出来就是下面这

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class Object
{
protected:
    string mName;
    string mInfo;
public:
    Object()
    {
        mName = "Object";
        mInfo = "";
    }
    
    string name()
    {
        return mName;
    }
    
    string info()
    {
        return mInfo;
    }
};

class Point : public Object
{
private:
    int mX;
    int mY;
public:
    Point(int x = 0, int y = 0)
    {
        ostringstream s;
        
        mX = x;
        mY = y;
        mName = "Point";
        
        s << "P(" << mX << ", " << mY << ")";
        
        mInfo = s.str();
    }
    
    int x()
    {
        return mX;
    }
    
    int y()
    {
        return mY;
    }
};

class Line : public Object
{
private:
    Point mP1;
    Point mP2;
public:
    Line(Point p1, Point p2)
    {
        ostringstream s;
        
        mP1 = p1;
        mP2 = p2;
        mName = "Line";
        
        s << "Line form " << mP1.info() << " to " << mP2.info() << "!";
        
        mInfo = s.str();        
    }
    
    Point begin()
    {
        return mP1;
    }
    
    Point end()
    {
        return mP2;
    }
};

int main()
{
    Object o;
    Point p(1, 2);
    Point pn(5, 6);
    Line l(p, pn);
    
    cout << o.name() << endl;
    cout << o.info() << endl;
    
    cout << endl;
    
    cout << p.name() << endl;
    cout << p.info() << endl;
    
    cout << endl;
    
    cout << l.name() << endl;
    cout << l.info() << endl;

    return 0;
}

        我们看看编译结果

技术分享图片

        我们看到在 Object 类中没有相应的描述,所以它的信息为空,别的打印是正确的。通过对继承中的访问级别的学习,总结如下:1、面向对象中的访问级别不只是 public 和 private;2、protected 修饰的成员不能被外界访问,它使得子类能够访问父类的成员;3、protected 关键字是为了继承而专门设计的;4、没有 protected 就无法完成真正意义上的代码复用。


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

以上是关于继承中的访问级别(三十七)的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer(三十七)之从上往下打印二叉树

EasyClick 原生UI连载三十七

Linux学习总结(三十七)lamp之禁止php解析 user_agent 访问控制 php相关配置

[系统安全] 三十七.APT系列远控木马详解与防御及APT攻击中的远控

C++--继承的概念和意义继承中的访问级别不同的继承方式

C#之三十七 实体类