C++中关于public、protect、private的访问权限控制

本文详细介绍了C++中public、protected和private访问控制的特点及应用,包括不同访问级别的成员如何被类实例和成员函数访问,以及在继承过程中的权限变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:成员的访问权限

1: public访问权限

    一个类的public成员变量、成员函数,可以通过类的成员函数、类的实例变量进行访问

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

   

#include<iostream>
#include<string>

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<string>
#include<iostream>

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<iostream>
#include<string>

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<iostream>
#include<string>

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<iostream>
#include<string>

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<iostream>
#include<string>

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继承


<think>好的,我现在需要解释C++中的protected访问修饰符。首先,我得回顾一下C++的访问控制机制,主要有publicprivateprotected三种。用户可能已经知道publicprivate的区别,但不太清楚protected的作用,特别是在继承中的表现。 用户的问题是关于protected修饰符的,我需要先给出基本定义。protected成员在类外部不可访问,这一点和private类似,但和private不同的是,protected成员可以被派生类访问。这点很关键,尤其是在继承体系中,派生类需要访问基类的某些成员时,protected就派上用场了。 接下来,我需要比较protected与publicprivate的区别。public成员在任何地方都可以访问,private只有类自己和友元可以访问,而protected允许类自身、派生类以及友元访问。这里可能需要举例说明,比如基类中的protected成员在派生类中可以直接使用,而private成员不行。 然后,应该讨论继承中的protected。比如,当使用公有继承时,基类的public成员在派生类中变为publicprotected成员保持protected,而private成员不可访问。如果是保护继承或私有继承,情况又会不同,但用户的问题可能更关注protected本身,所以可能需要简要提到不同继承方式的影响,但重点放在protected成员在派生类中的访问性。 还需要指出一些常见误区,比如派生类的对象不能直接访问基类的protected成员,只能通过派生类的成员函数访问。例如,如果有一个基类Base,里面有protected的变量x,派生类Derived的对象d不能直接d.x,但可以在Derived的成员函数中使用x。 另外,protected继承的概念可能需要解释,虽然用户的问题可能更多是关于成员的访问权限,但如果有必要,可以简要说明继承方式对访问权限的影响,比如使用protected继承时,基类的publicprotected成员在派生类中都变成protected。 可能还需要提到友元类和友元函数可以访问protected成员,这和private的情况类似,但用户可能已经了解这一点,所以可以简要带过。 最后,总结protected的使用场景,比如当需要允许派生类访问基类的某些成员,同时又不向外部公开时,使用protected。这有助于实现封装和继承的结合,增强代码的可维护性。 在组织内容时,需要结构清晰,分点说明,可能使用示例代码来辅助解释,但根据用户提供的代码示例,可能更倾向于文字描述,但适当加入代码片段会更直观。同时需要确保用词准确,避免歧义,比如强调派生类中的成员函数可以访问基类的protected成员,而对象实例不行。 还需要检查是否有常见的错误或注意事项,比如在派生类中覆盖基类的protected虚函数时的可见性,或者设计上的考量,比如过度使用protected可能导致封装性降低等。这些可以作为进阶内容提及,但用户可能更关注基础概念,所以需要平衡深度和广度。 最后,确保回答符合用户之前的格式要求,使用中文,结构清晰,分步骤或分点说明,可能使用加粗或列表来突出重点,但避免使用markdown格式。同时注意之前的对话历史,用户提供的代码中存在构造函数参数传递错误,可能在解释protected时,可以结合类似的例子,说明protected成员在继承中的正确使用,避免类似的错误。 现在需要将以上思考整理成一个连贯的回答,分点解释protected的作用、与其它修饰符的区别、继承中的表现、使用注意事项以及示例说明,确保覆盖用户可能关心的各个方面,同时指出常见错误和最佳实践。</think>以下是关于C++中`protected`访问修饰符的详细说明: --- ### **一、基本概念** `protected`是C++中的**访问控制修饰符**,用于控制类成员的可见性。其核心规则如下: - **类内部**:可直接访问(与`public`行为一致) - **派生类内部**:可直接访问(与`private`的关键区别) - **类外部**(包括对象实例):**不可访问**(与`private`行为一致) --- ### **二、与`public`/`private`的对比** | 修饰符 | 类内部 | 派生类 | 类外部 | |------------|--------|--------|--------| | `public` | ✔️ | ✔️ | ✔️ | | `protected`| ✔️ | ✔️ | ❌ | | `private` | ✔️ | ❌ | ❌ | --- ### **三、继承中的行为** #### 1. **基类成员的可见性变化** 继承方式会影响基类成员在派生类中的访问级别: - **公有继承(`public`)**: ```cpp class Base { protected: int x; // 基类protected成员 }; class Derived : public Base { void func() { x = 10; // ✔️ 可直接访问基类的protected成员 } }; ``` - **保护继承(`protected`)**: ```cpp class Derived : protected Base { // Base的public成员在此变为protected }; ``` - **私有继承(`private`)**: ```cpp class Derived : private Base { // Base的public/protected成员在此变为private }; ``` #### 2. **对象实例的限制** 即使通过继承,**派生类的对象仍无法直接访问基类的`protected`成员**: ```cpp Derived d; d.x = 10; // ❌ 编译错误!必须通过派生类的成员函数访问 ``` --- ### **四、典型使用场景** 1. **实现继承** 允许派生类直接操作基类的内部状态,同时对外隐藏细节。 *示例:基类`Shape`中定义`protected`的坐标数据,派生类`Circle`可直接修改这些坐标。* 2. **模板方法模式** 基类声明`protected`虚函数,派生类实现具体逻辑: ```cpp class Animal { protected: virtual void makeSound() = 0; // 由派生类实现 public: void speak() { makeSound(); } // 统一调用接口 }; ``` --- ### **五、注意事项** 1. **谨慎设计** 过度使用`protected`会破坏封装性,建议优先通过公有方法提供访问控制。 2. **友元例外** 友元类/函数可以访问`protected`成员: ```cpp class FriendClass { friend void specialAccess(); // 友元函数可访问所有成员的protected/private }; ``` 3. **构造/析构函数** 派生类的构造函数**无法直接初始化基类的`private`成员**,但可通过基类构造函数间接初始化: ```cpp class Base { protected: int value; // 允许派生类构造函数初始化 }; class Derived : public Base { public: Derived(int v) : Base{v} {} // ✔️ 正确方式 }; ``` --- ### **六、常见错误示例** ```cpp class Base { protected: int secret; }; class Derived : public Base { public: void leakSecret(Base& other) { other.secret = 5; // ❌ 错误!不能通过其他对象访问protected成员 } }; ``` *错误原因*:派生类只能访问**自己继承的**`protected`成员,不能访问其他对象(包括基类对象)的`protected`成员。 --- 通过合理使用`protected`,可以在继承体系中实现**受控的代码复用**,平衡封装性与扩展性的需求。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值