C++使用技巧(五):C类public,protected和 private的用法

一、用法说明

1.类的一个特征就是封装,public和private作用就是实现这一目的。所以:

用户代码(类外)可以访问public成员而不能访问private成员;private成员只能由类成员(类内)和友元访问。

2.类的另一个特征就是继承,protected的作用就是实现这一目的。所以:

protected成员可以被派生类对象访问,不能被用户代码(类外)访问。

二、理解与实践

先从类定义里理解public, 定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。

类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。例如,我们使用关键字 class 定义 Box 数据类型,如下所示:

class Box
{
   public:
      double length;   // 盒子的长度
      double breadth;  // 盒子的宽度
      double height;   // 盒子的高度
};

关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。
多说一点:

以上的类class类似结构体,因此不同的结构体名可共用类Box,并且对象 Box1 和 Box2 都有它们各自的数据成员:

Box Box1;          // 声明 Box1,类型为 Box
Box Box2;          // 声明 Box2,类型为 Box

参考文献:C++使用技巧(三):C++基类 & 派生类

谭浩强的《C++程序设计》中关于public,private和protected这三个成员访问限定符的概念性解释:

如果在类的定义中既不指定private,也不指定public,则系统就默认为是私有的。

被声明为私有的(private)成员,只能被本类中的成员函数引用,类外不能调用(友元类除外)。

被声明为公用的(public)成员,既可以被本类中的成员函数所引用,也可以被类的作用域内的其他函数引用。

用protected声明的成员称为受保护的成员,它不能被类外访问(这点与私有成员类似),但可以被派生类的成员函数访问。

3、 关于public、protect、private的访问权限控制

参考文献:
参考原文
一:成员的访问权限
1: public访问权限
一个类的public成员变量、成员函数,可以通过类的成员函数、类的实例变量进行访问

<实际上,类的成员函数,可以访问本类内的任何成员变量和成员函数>

#include
#include
 
using namespace std;
 
class AccessTest
{
	public:
		int pub_mem;
		int pub_fun(){};
	protected:
		int prot_mem;
		int prot_fun(){};
	private:
		int priv_memb;
		int priv_fun(){};
		
};
 
int main()
{
	AccessTest at;
	at.pub_mem;     //OK, 类变量可以访问public成员
	at.pub_func();  //OK, 访问public成员函数是没有问题的
	
  return 0;
}

2:protected访问权限
一个类的protected成员变量、成员函数,无法通过类的实例变量进行访问。但是可以通过类的友元函数、友元类进行访问。

#include
#include
 
using namespace std;
 
class AccessTest
{
    friend void Atest();
    friend class CAtest;
    public:
        int pub_mem;
        void pub_fun(){}
    protected:
        int prot_mem;
        void prot_fun(){}
    private:
        int priv_memb;
        void priv_fun(){}
        
};
 
class CAtest
{
    public:
        void x()
        {
          AccessTest t;
          t.prot_fun();      //OK,友元类可以访问protected成员函数
          int x=t.prot_mem;  //OK,友元类可以访问protected成员变量
       }
};
 
void Atest()
{
    AccessTest t;
    t.prot_fun();     //OK,友元函数可以访问protected成员函数
    int x=t.prot_mem;  //OK,友元函数可以访问protected成员变量
}
 
int main()
{
    AccessTest at;
    at.prot_mem;      //ERROR,类实例变量无法访问protected成员变量
    at.prot_fun();    //ERROR,类实例变量无法访问protected成员函数
    Atest();
    return 0;
}

3:private访问权限
一个类的private成员变量、成员函数,无法通过类的实例变量进行访问。但是可以通过类的友元函数、友元类进行访问。

#include
#include
 
using namespace std;
 
class AccessTest
{
	friend void Atest();
	friend class CAtest;
	public:
		int pub_mem;
		void pub_fun(){}
	protected:
		int prot_mem;
		void prot_fun(){}
	private:
		int priv_memb;
		void priv_fun(){}
		
};
 
class CAtest
{
	public:
	void x()
	{
	       AccessTest t;
    	       t.priv_fun();       //OK,友元类可以访问private成员函数
	       int x=t.priv_memb;  //OK,友元类可以访问private成员变量
        }
};
 
void Atest()
{
	AccessTest t;
	t.priv_fun();       //OK,友元函数可以访问private成员函数
	int x=t.priv_memb;  //OK,友元函数可以访问private成员变量
}
 
int main()
{
	AccessTest at;
	at.priv_memb;       //ERROR,类实例变量无法访问private成员变量
	at.priv_fun();      //ERROR,类实例变量无法访问private成员函数
	Atest();
        return 0;
}

到现在,是否感觉私有访问属性,和保护属性没有什么区别?区别主要体现在继承上面。下面将会讲到。

总结:public在任何地方都能访问,protected只能在派生类中访问, private只能在友元中访问。

二:继承的访问权限控制
1:public继承
派生类通过public继承,基类的各种权限不变 。

 派生类的成员函数,可以访问基类的public成员、protected成员,但是无法访问基类的private成员。

 派生类的实例变量,可以访问基类的public成员,但是无法访问protected、private成员,仿佛基类的成员之间加到了派生类一般。

 可以将public继承看成派生类将基类的public,protected成员囊括到派生类,但是不包括private成员。
#include
#include
 
using namespace std;
 
class AccessTest
{
	public:
		int pub_mem;
		void pub_fun(){}
	protected:
		int prot_mem;
		void prot_fun(){}
	private:
		int priv_memb;
		void priv_fun(){}
		
};
 
class DAccessTest:public AccessTest
{
	public:
		void test()
		{
			int x=pub_mem;     //OK
			pub_fun();         //OK
			
			int y=prot_mem;    //OK
			prot_fun();        //OK
			
			int z=priv_memb;   //ERROR
			priv_fun();        //ERROR
		}
		
};
 
 
 
int main()
{
	DAccessTest dt;
	int x=dt.pub_mem;    //OK
	int y=dt.prot_mem;   //ERROR
	int z=dt.priv_memb;  //ERROR
        return 0;
}

2:protected继承
派生类通过protected继承,基类的public成员在派生类中的权限变成了protected 。protected和private不变。
派生类的成员函数,可以访问基类的public成员、protected成员,但是无法访问基类的private成员。

 派生类的实例变量,无法访问基类的任何成员,因为基类的public成员在派生类中变成了protected。

 可以将protected继承看成派生类将基类的public,protected成员囊括到派生类,全部作为派生类的protected成员,但是不包括private成员。

 private成员是基类内部的隐私,除了友元,所有人员都不得窥探。派生类的友元,都不能访问
#include
#include
 
using namespace std;
 
class AccessTest
{
    friend void Atest();
    friend class CAtest;
    public:
        int pub_mem;
        void pub_fun(){}
    protected:
        int prot_mem;
        void prot_fun(){}
    private:
        int priv_memb;
        void priv_fun(){}
        
};
 
class DAccessTest:protected AccessTest
{
    public:
        void test()
        {
            int x=pub_mem;     //OK
            pub_fun();         //OK
            
            int y=prot_mem;    //OK
            prot_fun();        //OK
            
            int z=priv_memb;   //ERROR
            priv_fun();        //ERROR
        }
        
};
 
 
 
int main()
{
    DAccessTest dt;
    int x=dt.pub_mem;    //ERROR,基类的成员现在是派生类的保护成员
    int y=dt.prot_mem;   //ERROR,基类的成员现在是派生类的保护成员
    int z=dt.priv_memb;  //ERROR
  return 0;
}
 
 
 
 
 

3:private继承

 派生类通过private继承,基类的所有成员在派生类中的权限变成了private。
 派生类的成员函数,可以访问基类的public成员、protected成员,但是无法访问基类的private成员。

 派生类的实例变量,无法访问基类的任何成员,因为基类的所有成员在派生类中变成了private。

 可以将private继承看成派生类将基类的public,protected成员囊括到派生类,全部作为派生类的private成员,但是不包括private成员。

 private成员是基类内部的隐私,除了友元,所有人员都不得窥探。派生类的友元,都不能访问
#include
#include
 
using namespace std;
 
class AccessTest
{
	friend void Atest();
	friend class CAtest;
	public:
		int pub_mem;
		void pub_fun(){}
	protected:
		int prot_mem;
		void prot_fun(){}
	private:
		int priv_memb;
		void priv_fun(){}
		
};
 
class DAccessTest:private AccessTest
{
	public:
		void test()
		{
			int x=pub_mem;     //OK
			pub_fun();         //OK
			
			int y=prot_mem;    //OK
			prot_fun();        //OK
			
			int z=priv_memb;   //ERROR
			priv_fun();        //ERROR
		}
		
};
 
 
 
int main()
{
	DAccessTest dt;
	int x=dt.pub_mem;    //ERROR,基类的成员现在是派生类的私有成员
	int y=dt.prot_mem;   //ERROR,基类的成员现在是派生类的私有成员
	int z=dt.priv_memb;  //ERROR, private成员无法访问
  return 0;
}

总结:继承修饰符,就像是一种筛子,将基类的成员筛到派生类。public、protected、private,就是筛子的眼。

      通过public继承,所有基类成员(除了private),public、protected都到了派生类里面,public筛眼比较大,不会改变访问权限。

      通过protected继承,所有基类成员(除了private),public、protected都到了派生类里面,protected筛眼大小适中,所有过来的成员都变成了protected。

      通过private继承,所有基类成员(除了private),public、protected都到了派生类里面,private筛眼最小,所有过来的成员都变成了private。

PS:关于class和struct的区别
1:class不写修饰符,成员默认是private的,而struct 默认是public的

class Base   //默认private
{
    int a;
    int b;
}
 
Base ba;
int x=ba.a;//错误
int y=ba.b;//错误
 
struct St  //默认public
{
    int a;
    int b;
};
 
St st;
int x=st.a; //OK
int y=st.b;//OK

2:class的继承默认是private的,而struct默认是public的

class Base{...};
class Derive:Base{...}  //private继承
 
struct BStruct{...};
struct DStruct:BStruct{...};//public继承

你可能感兴趣的:(c++)