C++中类成员的访问控制权限

引入三种访问控制符

C++中,存在三种访问控制修饰符,它们分别是:

  • public // 公有成员
  • protected // 保护成员
  • private // 私有成员

术语

为了使文章容易理解,我们首先对以下术语作出说明:

  • 对象: 与类相对,对象是类的实例。
  • 派生类:与基类相对,派生类就是子类。
  • 继承:继承与派生是一个意思。继承偏重指出此过程中不变的部分,而派生则偏重于在原有基础上新增的部分。
  • 成员:类中成员变量和成员函数的统称。

对象的访问权限

在以下的例子中,我们创建了一个简单的类。
下面,我们就来探究一下,对于该类中被不同访问控制修饰符修饰的成员,该类的对象都有什么样的访问权限。

#include <iostream>

using namespace std;

class CBase
{
private:
    int a_base_private;
protected:
    int b_base_protected;
public:
    int c_base_public;

public:
    CBase(){a_base_private = 1; b_base_protected = 2; c_base_public = 3;}
    ~CBase(){}

    int getA() const {return a_base_private;}       // OK, 类可以访问自身的所有成员
    int getB() const {return b_base_protected;}     // OK, 类可以访问自身的所有成员
    int getC() const {return c_base_public;}        // OK, 类可以访问自身的所有成员
};

int main()
{
    int tmp;
    CBase baseObj;

    //baseObj.a_base_private = 1;           // KO, 对象不能访问类的private成员
    //baseObj.b_base_protected = 1;         // KO, 对象不能访问类的protected成员
    baseObj.c_base_public = 1;              // OK, 对象可以访问类的public成员

    tmp = baseObj.getA();       // OK, 对象可以访问类的public成员
    tmp = baseObj.getB();       // OK, 对象可以访问类的public成员
    tmp = baseObj.getC();       // OK, 对象可以访问类的public成员
}

从以上实践中可以得出以下结论:

  1. 类可以访问自身的所有成员,不论是private, protected 还是 public。
  2. 对象只能访问类的public成员。

友元的访问权限

在以上例子的基础上,让我们来考虑一下,对于该类中被不同访问控制修饰符修饰的成员,该类的友元函数和友元类对这些成员都有什么样的访问权限。

#include <iostream>

using namespace std;

class CBase;
class CFriend;
void ClearBaseA(CBase &obj);

class CBase
{
friend  CFriend;                            // 声明CFriend为自己的友元类
friend  void ClearBaseB(CBase &obj);        // 声明ClearBaseA为自己的友元函数

private:
    int a_base_private;
protected:
    int b_base_protected;
public:
    int c_base_public;

public:
    CBase(){a_base_private = 1; b_base_protected = 2; c_base_public = 3;}
    ~CBase(){}

    int getA() const {return a_base_private;}       // OK, 类可以访问自身的所有成员
    int getB() const {return b_base_protected;}     // OK, 类可以访问自身的所有成员
    int getC() const {return c_base_public;}        // OK, 类可以访问自身的所有成员
};

class CFriend
{
private:
    CBase obj;

public:
    CFriend(){}
    ~CFriend(){}

    int setBaseA(int f) {obj.a_base_private = f;}       // OK, 在友元类中,可以访问Base类的私有成员
    int getBaseA() const {return obj.getA();}
};

void ClearBaseB(CBase &obj)
{
    obj.b_base_protected = 0;           // OK, 在友元函数中,可以访问Base类的保护成员
}

int main()
{
    int tmp;
    CBase baseObj;
    CFriend friendObj;

    cout << baseObj.getB() << endl;     // 通过构造函数初始化为2
    ClearBaseB(baseObj);
    cout << baseObj.getB() << endl;     // 被友元函数给清0了

    cout << friendObj.getBaseA() << endl;   // 通过构造函数初始化为1
    friendObj.setBaseA(7);
    cout << friendObj.getBaseA() << endl;   // 被友元类给设置为了7
}

由上例中可以看出,友元可以访问类中的private和protected成员,对于public成员,当然更是可以访问的了,虽然以上例子中并没有验证这一点。
所以,我们可以得出以下结论:

  1. 友元函数或友元类可以访问类中的所有成员。

小结

我们换一个角度,通过以下表格总结一下。

访问控制修饰符 对象 友元
public 可访问 可访问 可访问
protected 可访问 不可访问 可访问
private 可访问 不可访问 可访问

引入三种继承方式

在C++中,在继承的过程中,有以下三种继承方式,它们分别是:

  • public (公有继承)
  • protected (保护继承)
  • private (私有继承)
    这三个关键字与之前的三种访问控制修饰符刚好相同,但在这里,它们有不同的意义。
  1. 对于public继承,基类中的成员的访问控制修饰符不作任何改动,原样继承到派生类中。
    也就是说,基类中的public成员,到了派生类中,仍然是派生类的public成员;基类中的protected成员,到了派生类中,仍然是protected成员;基类中的private成员,它对派生类不可见。
  2. 对于protected继承,基类中的public成员,在派生类中被派生为protected成员;基类中的protected成员,在派生类中仍然是protected成员;基类中的private成员,在派生类不可见。
  3. 对于private继承,基类中的public和protected成员,在派生类中,均被派生为了private成员;而基类中的private成员,对派生类不可见。

public继承方式

在第一个例子的基础之上,我们通过public方式继承出一个新的派生类。

#include <iostream>

using namespace std;

class CBase
{
private:
    int a_base_private;
protected:
    int b_base_protected;
public:
    int c_base_public;

public:
    CBase(){a_base_private = 1; b_base_protected = 2; c_base_public = 3;}
    ~CBase(){}

    int getA() const {return a_base_private;}       // OK, 类可以访问自身的所有成员
    int getB() const {return b_base_protected;}     // OK, 类可以访问自身的所有成员
    int getC() const {return c_base_public;}        // OK, 类可以访问自身的所有成员
};

class CDerived:public CBase
{
private:
    int x_derived_private;
protected:
    int y_derived_protected;
public:
    int z_derived_private;

public:
    CDerived(){x_derived_private = 4; y_derived_protected = 5; z_derived_private = 6;}
    ~CDerived(){}

    //void setBaseA(int t){a_base_private = t;}     // KO, 派生类中不能访问基类的private成员
    void setBaseB(int t){b_base_protected = t;}     // OK, 派生类中可以访问基类的protected成员
    void setBaseC(int t){c_base_public = t;}        // OK, 派生类中可以访问基类的public成员  

    int getX() const {return x_derived_private;}
    int getY() const {return y_derived_protected;}
    int getZ() const {return z_derived_private;}
};

int main()
{
    CDerived derivedObj;

    //derivedObj.a_base_private = 1;            // KO, 基类中由private修饰的a_base_private,对派生类是不可见的,即使在派生类中都不能访问,更别提派生类对象了。
    //derivedObj.b_base_protected = 1;          // KO, 对象不能访问类的protected成员(public方式继承的protected成员,在派生类中仍为protected成员)
    derivedObj.c_base_public = 1;               // OK, 对象可以访问类的public成员(public方式继承的public成员,在派生类中仍为public成员)

    cout << derivedObj.getA() << endl;      // OK, 对象可以访问类的public成员(public方式继承的public成员,在派生类中仍为public成员)
    derivedObj.setBaseB(8);                 // OK, 对象可以访问类的public成员
    cout << derivedObj.getB() << endl;      // OK, 对象可以访问类的public成员(public方式继承的public成员,在派生类中仍为public成员)
    derivedObj.setBaseC(9);                 // OK, 对象可以访问类的public成员
    cout << derivedObj.getC() << endl;      // OK, 对象可以访问类的public成员(public方式继承的public成员,在派生类中仍为public成员)
}

由以上例子可以看出:

  1. 基类中的private, protected, public成员,经由public继承之后,在派生类中分别为不可见private, protected,public成员。
  2. 派生类中不能访问基类的private成员,但可以访问基类的private和protected成员。

protected继承方式

在第一个例子的基础之上,我们通过protected方式继承出一个新的派生类。

#include <iostream>

using namespace std;

class CBase
{
private:
    int a_base_private;
protected:
    int b_base_protected;
public:
    int c_base_public;

public:
    CBase(){a_base_private = 1; b_base_protected = 2; c_base_public = 3;}
    ~CBase(){}

    int getA() const {return a_base_private;}       // OK, 类可以访问自身的所有成员
    int getB() const {return b_base_protected;}     // OK, 类可以访问自身的所有成员
    int getC() const {return c_base_public;}        // OK, 类可以访问自身的所有成员
};

class CDerived:protected CBase
{
private:
    int x_derived_private;
protected:
    int y_derived_protected;
public:
    int z_derived_private;

public:
    CDerived(){x_derived_private = 4; y_derived_protected = 5; z_derived_private = 6;}
    ~CDerived(){}

    //void setBaseA(int t){a_base_private = t;}     // KO, 派生类中不能访问基类的private成员
    void setBaseB(int t){b_base_protected = t;}     // OK, 派生类中可以访问基类的protected成员
    void setBaseC(int t){c_base_public = t;}        // OK, 派生类中可以访问基类的public成员

    int getX() const {return x_derived_private;}    // OK, 类可以访问自身的所有成员
    int getY() const {return y_derived_protected;}  // OK, 类可以访问自身的所有成员
    int getZ() const {return z_derived_private;}    // OK, 类可以访问自身的所有成员
};

int main()
{
    CDerived derivedObj;

    //derivedObj.a_base_private = 1;            // KO, 对象不能访问类的private成员(protected方式继承的private成员,在派生类中不可见)
    //derivedObj.b_base_protected = 1;          // KO, 对象不能访问类的protected成员(protected方式继承的protected成员,在派生类中仍为protected成员)
    //derivedObj.c_base_public = 1;             // KO, 对象不可以访问类的protected成员(protected方式继承的public成员,在派生类中成为protected成员)

    //cout << derivedObj.getA() << endl;        // KO, 对象不可以访问类的protected成员(protected方式继承的public成员,在派生类中成为protected成员)
    //cout << derivedObj.getB() << endl;        // KO, 对象不可以访问类的protected成员(protected方式继承的public成员,在派生类中成为protected成员)
    //cout << derivedObj.getC() << endl;        // KO, 对象不可以访问类的protected成员(protected方式继承的public成员,在派生类中成为protected成员)
}

由以上例子可以看出:

  1. 基类中的private, protected, public成员,经由protected继承之后,在派生类中分别为不可见private, protected,protected成员。
  2. 派生类中不能访问基类的private成员,但可以访问基类的private和protected成员。

private继承方式

在第一个例子的基础之上,我们通过private方式继承出一个新的派生类。

#include <iostream>

using namespace std;

class CBase
{
private:
    int a_base_private;
protected:
    int b_base_protected;
public:
    int c_base_public;

public:
    CBase(){a_base_private = 1; b_base_protected = 2; c_base_public = 3;}
    ~CBase(){}

    int getA() const {return a_base_private;}       // OK, 类可以访问自身的所有成员
    int getB() const {return b_base_protected;}     // OK, 类可以访问自身的所有成员
    int getC() const {return c_base_public;}        // OK, 类可以访问自身的所有成员
};

class CDerived:private CBase
{
private:
    int x_derived_private;
protected:
    int y_derived_protected;
public:
    int z_derived_private;

public:
    CDerived(){x_derived_private = 4; y_derived_protected = 5; z_derived_private = 6;}
    ~CDerived(){}

    //void setBaseA(int t){a_base_private = t;}     // KO, 派生类中不能访问基类的private成员,因为其在派生类中不可见
    void setBaseB(int t){b_base_protected = t;}     // OK, 派生类中可以访问基类的protected成员
    void setBaseC(int t){c_base_public = t;}        // OK, 派生类中可以访问基类的public成员

    int getX() const {return x_derived_private;}    // OK, 类可以访问自身的所有成员
    int getY() const {return y_derived_protected;}  // OK, 类可以访问自身的所有成员
    int getZ() const {return z_derived_private;}    // OK, 类可以访问自身的所有成员
};

int main()
{
    CDerived derivedObj;

    //derivedObj.a_base_private = 1;            // KO, (private方式继承的private成员,在派生类中不可见)
    //derivedObj.b_base_protected = 1;          // KO, (private方式继承的protected成员,在派生类中不可见)
    //derivedObj.c_base_public = 1;             // KO, (private方式继承的public成员,在派生类中成为不可见)

    //cout << derivedObj.getA() << endl;        // KO, (private方式继承的public成员,在派生类中不可见)
    //cout << derivedObj.getB() << endl;        // KO, (private方式继承的public成员,在派生类中不可见)
    //cout << derivedObj.getC() << endl;        // KO, (private方式继承的public成员,在派生类中不可见)

    cout << derivedObj.getX() << endl;
    cout << derivedObj.getY() << endl;
    cout << derivedObj.getZ() << endl;
}

由以上例子可以看出:

  1. 基类中的private, protected, public成员,经由private继承之后,在派生类中均不可见。
  2. 派生类中不能访问基类的private成员,但可以访问基类的private和protected成员。

小结

  • 不论何种继承方式,派生类都不能访问基类的private成员,它只能访问基类的public和protected成员。
  • 三种继承方式对不同访问控制符修饰的成员的影响如下表所示。
访问控制修饰符 public继承 protected继承 private继承
public public protected private
protected protected protected private
private private private private

总结

  1. 友元和类一样,可以访问类的所有成员。
  2. 对象只能访问类的public成员。
  3. 派生类只能访问基类的public和protected成员,而不能访问基类的private成员。
  4. 对于派生出来的类,首先根据继承方式,确定基类各成员在经指定的继承方式继承后的访问控制权限(经继承后基类各成员是变成了public,protected还是private),然后根据第1、2、3点对各成员进行访问。
  5. 经继承后,基类中的成员会根据继承方式,对各成员的访问控制符进行修改。修改之后,基类中的private成员对派生类不可见。

参考文献

原文地址:https://www.cnblogs.com/outs/p/10128993.html

时间: 2024-10-12 09:58:25

C++中类成员的访问控制权限的相关文章

Delphi XE中类成员的访问权限(新增了strict private和strict protected,还有automated)

Delphi XE中类成员的访问权限共提供了6个关键词来用于限定访问权限:public.private.protected.published.automated strict private . strict protected其各自的含义为: 1. strict private:此区定义的字段或方法只能用于当前的类中.即T1中此区定义的成员只能在T1中使用.2. strict protected:此区定义的成员除能用于当前类中,还可用于当前类的任何子类中. 以上两种成员,同一个类的不同对象间

Java访问控制权限

Java的访问控制权限相比于C++等语言可能稍微复杂一点,不过也不难理解.Java的访问控制权限分为两块--"类或接口的访问控制权限"与"变量和方法的访问控制权限". 1.类或接口的访问控制权限     类或接口的访问控制权限是指能不能用该类建立对象,接口能不能被实现等等.能够修饰类或接口的访问控制权限的修饰符(modifier)只有两个--public和friendly.不过,值得一说的是friendly并不是Java的关键字,它只是一个习惯叫法,指的是"

访问控制权限

访问控制权限 访问控制权限的等级,从最大权限到最小权限依次为:public,protected,包访问权限(没有关键字)和private. 默认访问权限没有任何关键字,但通常是指包访问权限.这就意味着当前包中的其他所有类对那个成员都有访问权限,但对于这个包之外的所有类,这个成员却是private.由于一个编译单元只能隶属于一个包,所以经由包访问权限,处于同一个编译单元的所有类彼此之间是自动可访问的.包访问权限允许将包内所有相关的类组合起来,以使它们之间可以轻松的相互作用. public:接口访问

JAVA 基础 访问控制权限

包(package) package的作用 当编写一个JAVA源码文件时,此文件通常被称为编译单元.每个编译单元都必须有一个后缀名 .java . 而在编译单元中可以有一个 public 类,该类的名称必须和文件的名称相同.文件中允许有其他类,但是不能是public类. 当编译一个 .java 文件时,文件中的每个类都会有一个后缀为 .class 的输出文件,文件名和类名相同. Java可运行程序是一组可以打包压缩为一个Java文档文件(JAR,使用Java的jar文档生成器)的.class文件

java访问控制权限和C++访问控制权限的对比

1.java修饰符权限 这里有一个包的概念,所谓同一个包是指*.java文件处于同一个文件夹下 2.C++修饰符权限 public:这是公有的成员,允许类外直接访问,当然,这要加上类作用域符::, protected:这是保护成员,只允许该类及其派生类访问 private:这是私有成员,只允许在该类中进行访问,当然,在类外只可以通过设定的公有函数进行访问. java访问控制权限和C++访问控制权限的对比

鸡啄米:C++编程之十三学习之类与对象,类的声明,成员的访问控制

1. 本次学习鸡啄米课程第13篇,把比较重要的学习记录下来,以敦促自己更好的学习.推荐他们的网址学习:http://www.jizhuomi.com/school/c/97.html 2. 在面向过程的设计中,程序的模块是函数构成的,而面向对象设计中程序模块是类构成的,函数只是语句和数据的封装,而类是函数和数据的封装,做了一段C++之后,才明白这句话的意思.其实类就是一种自定义的数据类型.可以定义某个类类型的变量,用类定义的变量叫做类的对象,这种定义对象的过程叫做实例化. 3. 不过一直有个疑问

Java成员的访问权限控制

Java中的访问权限控制包含两个部分: 类的访问权限控制 类成员的访问权限控制 对类来说,访问权限控制修饰符可以是public或者无修饰符(默认的包访问权限): 对于类成员来说,访问权限控制修饰符可以是public,protected, package private(无修饰符), or private. 以下表格总结了类成员中不同访问权限控制修饰符对应的访问级别:

Java——private default protected public访问控制权限

访问控制权限 protected范例

成员方法与成员变量访问权限的求证

package com.jaovo; /** *_1_ 成员变量访问权限的求证 * public private protected default(默认的权限) *自己包自己类 可访问 可访问 可访问 可访问 *自己包别的类 可访问 不可访问 可访问 可访问 *别的包别的类 可访问 不可访问 不可访问 不可访问 *自己包别的类有继承关系 可访问 不可访问 可访问 可访问 *别的包别的类有继承关系 可访问 不可访问 可访问 不可访问 *------------------------------