2、继承中的访问级别

此文编写参考狄泰软件学院唐佐林老师的视频课程

一、子类可以直接访问父类的私有成员吗?

1、对于这个问题的两个不同的视角

(1)、根据面向对象的理论,因为子类拥有父类的一切行为何属性,因此应该可以直接访问父类的私有成员。
(2)、根据c++语法本身,因为外界不能够直接访问类的private成员,因此子类不可以访问父类的私有成员。
那么实际情况是怎样的呢?下面通过实验便知。

#include<iostream>
using namespace std;
class Parent 
{
private:
	int value;
public:
	Parent()
	{
		value=100;
	}
	int get_value()
	{
		return value;
	}
};
class Child:public Parent
{
public:
	int add_Value(int m)
	{
		value=m+value;//此处是访问了父类的私有成员
	}
};
int main()
{
	return 0;
}

结果:
在这里插入图片描述
运行结果表明了该程序的编写是有错误的,那么原因又是什么呢?具体请看下面内容。

2、三种访问级别

事实上之前的两种视角都是没有错的,这个只是访问级别的问题,在c++中不只只有public和private这两种访问级别,还存在一种叫protected的访问级别,那么proteced的意义是什么呢?
protected的意义:

  1. 修饰的成员不能够被外界访问
  2. 修饰的成员可以被子类直接访问

我们可以通过生活中的实例来理解protected的意义,因为c++是面向对象的语言,是可以用程序来描述生活问题的。对于一个公司的女生而言,可能她的身高和体重是不希望被别人知道的,所以这个就可以看成是私有成员,但是她的姓名是大家都知道的,因此可以看成是公有成员,然而对于她在公司里的薪资是保密的,但是她可以告知她的家里人,所以这个私密性就介于公有属性和私有属性之间了,在c++中就是用protected这个关键字来描述问题了。

学了protected这个关键字之后,我们就可以用它来修改一下上面的这个程序了,也就是将上面程序中的父类中的私有属性改成protected。为加深对这三种访问级别,程序修改后如下所示:

#include<iostream>
using namespace std;
class Parent 
{
protected:
	int value;
public:
	Parent()
	{
		value=100;
	}
	int get_value()
	{
		return value;
	}
};
class Child:public Parent
{
public:
	int add_Value(int m)
	{
		 value=value+m;
	}
};

int main()
{
	Parent p1;//创建一个父类对象
	//p1.value=200;//error,因为这里直接访问value相当是外界直接访问
	cout<<"value="<<p1.get_value()<<endl;

	Child c1;//创建一个子类对象
	//c1.value=200;//error,因为这里直接访问value相当是外界直接访问
	cout<<"value="<<c1.get_value()<<endl;//c1继承了父类的属性和行为

	c1.add_Value(100);//子类可以直接访问父类的protected成员
	cout<<"value="<<c1.get_value()<<endl;//通过这个加法证明是访问成功的

	return 0;
}

在这里插入图片描述

3、如何选择合适的访问级别

在这里插入图片描述
该图中有两个分支,其实逻辑非常简单,首先我们在定义类的时候就应该思考一下,这个类以后是否有可能被继承,当有这个可能的时候,这个时候我们就应该注意了,定义成员的时候,我们希望这个成员能够被外界访问吗,这里的外界是指全局函数或者是与该类没有任何关系的其他类,如果希望能够被访问,那么就定义为public,如果不希望被访问,那么这个时候就要考虑该类希望被以后的子类访问吗,如果希望被子类访问,那么这时就应该定义成protected的访问级别,否则就定义成private的访问级别。

二、组合与继承综合实例

此例要用c++来描述下图中的关系。
在这里插入图片描述

#include<iostream>
#include<string>
#include<sstream>
using namespace std;
class Object
{
protected:
	//因为是用这两个成员变量来描述问题,所以最终要输出的就是这两个成员变量的信息,因为注定要被继承,所以用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)
	{
		mX=x;
		mY=y;
		mName="Point";//直接使用Object的成员变量
		ostringstream oss;
		oss<<"Point("<<mX<<","<<mY<<")";
		mInfo=oss.str();//直接使用Object的成员变量
	}
	int x()
	{
		return mX;
	}
	int y()
	{
		return mY;
	}
};
class Line:public Object//继承Object
{
private:
	Point mP1;//与Point构成组合关系,也就是同生死的关系
	Point mP2;//与Point构成组合关系,也就是同生死的关系
public:
	Line(Point p1,Point p2)
	{
		mP1=p1;
		mP2=p2;
		mName="Line";//直接使用Object的成员变量
		ostringstream oss;
		oss<<"Line from "<<mP1.info()<<" to "<<mP2.info();
		mInfo=oss.str();//直接使用Object的成员变量
	}
	Point begin()
	{
		return mP1;
	}
	Point end()
	{
		return mP2;
	}
};
int main()
{
	Object o//创建一个实体对象o
	Point p1(0,0);
	Point p2(8,8);
	Line line(p1,p2);//将p1,p2连接成线
    //打印信息
	cout<<o.name()<<endl;
	cout<<o.info()<<endl;
	cout<<endl;

	cout<<p1.name()<<endl;
	cout<<p1.info()<<endl;
	cout<<endl;

	cout<<p2.name()<<endl;
	cout<<p2.info()<<endl;
	cout<<endl;

	cout<<line.name()<<endl;
	cout<<line.info()<<endl;
	cout<<endl;
	
	return 0;
}

运行结果:
在这里插入图片描述

三、总结

  1. c++中面向对象的访问级别有private,public,protected
  2. protected修饰的成员不能够被外界访问
  3. protected使得子类可以访问父类的成员
  4. protected这个关键字是专门为了继承而设计的
  5. 没有protected就没有办法完成真正意义上的代码复用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值