一篇讲述C++中的友元机制及类中成员的私密性

<1>必备知识

私密程度: public < protected < private

public:无访问限制可以被任何地方访问,包括类的内部、外部、类的派生类以及类的成员函数。

protected:较为开放,可以被该类的成员函数友元派生类的成员函数访问。

private:只允许该类的成员函数和友元访问,不允许派生类访问。

举例说明:

创建了一个Students类,内部有public,protected,private三种类型的成员

class Student
{
    public:
    std::string pub_name;
    short pub_age;
    std::string pub_gantal;

    protected:
        long pro_sno;

    
    private:
        long pri_phonenumber;
        std::string pri_address;

    public:
       
       void initPubInfo(std::string pub_name,short pub_age,std::string pub_gantal)
       {
        this->pub_name = pub_name;
        this->pub_age  = pub_age;
        this->pub_gantal = pub_gantal;
       }

       void showPubInfo()
       {
        std::cout<<"name: "<<this->pub_name<<","
                 <<"age: "<<this->pub_age<<","
                 <<"gental: "<<this->pub_gantal<<std::endl;
       }

       void initProInfo(long pro_sno)
       {
        this->pro_sno = pro_sno;
       }

       void showProInfo()
       {
        std::cout<<"student's sno: "<<this->pro_sno<<std::endl;
       }

       void initPriInfo(long pri_phonenumber,std::string pri_address)
       {
        this->pri_phonenumber = pri_phonenumber;
        this->pri_address = pri_address;
       }

       void showPriInfo()
      {
        std::cout<<"phone number: "<<this->pri_phonenumber<<","
        <<"address: "<<this->pri_address<<std::endl;
      }
};

(1)三者均可被该类的成员函数访问:

1.首先验证public类型成员:

Student* student = new Student();
    student->initPubInfo("Jack",24,"男");
    student->showPubInfo();

控制台输出:

public成员还能在任何地方被修改,调用:

Student* student = new Student();
    student->pub_age=24;
    student->pub_gantal="女";
    student->pub_name="Jack";
    std::cout<<student->pub_age<<","
             <<student->pub_gantal<<","
             <<student->pub_name<<std::endl;

控制台输出:

验证成功!

2.验证protected:

Student* student = new Student();
    student->initProInfo(2024854);
    student->showProInfo();

控制台输出:

成功验证其能被该类的成员函数访问!

3.验证private:

Student* student= new Student();
    student->initPriInfo(18392893222,"ShangHai");
    student->showPriInfo();

控制台输出:

成功验证其能被该类的成员函数访问!

(2)验证私密性

protected与private成员均不能在类外部被访问:

软件界面未给出我们选择protected与privated成员的访问选项,强行访问会导致编译器报错!只给出了public成员的访问选项,验证成功!

(3)验证派生类是否可以访问

创建派生类:Entity

class Entity : public Student
{
    public:
        
        void Doing()
        {
            
        }
}

(或许有的小伙伴会存有疑问,为什么时public Student,而不是protected Student ,private Student,这里做出解释:

在 C++ 中,继承是通过指定继承类型来控制基类成员的访问权限。public, protected, 和 private 这三种继承方式各自有不同的行为,它们会影响基类成员在派生类中的访问权限。具体来说,使用 public Student 而不是 protected Studentprivate Student 的原因如下:

1. public 继承

  • 访问权限:基类的 public 成员在派生类中仍然是 public,而基类的 protected 成员在派生类中仍然是 protected,基类的 private 成员依然无法访问。
  • 外部访问:通过 public 继承,基类的 public 成员对所有使用派生类对象的外部代码都是可访问的。这意味着可以直接使用派生类对象访问基类的 public 成员。

2. protected 继承

  • 访问权限:基类的 public 成员在派生类中变为 protected,这意味着外部代码无法直接访问它们。只有通过派生类的成员函数才能访问这些成员。
  • 外部访问:通过 protected 继承,派生类对象的外部代码无法直接访问基类的 public 成员。

3. private 继承

  • 访问权限:基类的所有成员(无论是 public 还是 protected)在派生类中都变为 private,这意味着外部代码无法访问这些成员。
  • 外部访问:通过 private 继承,派生类对象的外部代码完全无法访问基类的成员,包括 publicprotected 成员。

预在派生类中访问Student类中成员时,只提供了public与protected成员选项,强行访问private成员会报错!

得出结论private成员无法在派生类中被调用!

(4)验证友元函数

概念:

友元函数是一种可以访问类的私有和保护成员的非成员函数。虽然它不是类的成员,但由于使用了 friend 关键字,类授予了它访问私有和保护成员的权限。

特点:
  • 友元函数并不属于类的成员,因此不能通过对象直接调用,需要通过常规的函数调用方式使用。
  • 友元函数的声明在类的内部,定义可以在类的外部。
  • 友元函数可以是全局函数、其他类的成员函数,甚至是静态函数。

在Student类中声明友元函数,可在类内部声明,类内部定义,也可以在类内部声明,类外部定义友元函数。

friend void doingInfo1(Student& obj)
      {
        obj.pro_sno =1234;
        obj.pri_phonenumber = 18192090902;
        std::cout<<obj.pro_sno<<std::endl;
        std::cout<<obj.pri_phonenumber<<std::endl;
      }
      friend void doingInfo2(Student& obj);
void doingInfo2(Student& obj)
{
    obj.pri_address = "BeiJing";
    obj.pro_sno=123;
    std::cout<<obj.pri_address<<std::endl;
    std::cout<<obj.pro_sno<<std::endl;
}

经验证代码正常运行,可验证友元函数可以访问protected与private成员。

(5)验证友元类

概念:

友元类是一个类,它可以访问另一个类的所有私有和保护成员。被声明为友元类的类相当于有权访问另一个类的私有实现细节。

特点:
  • 友元类的所有成员函数(包括构造函数、析构函数等)都可以访问被授予友元权限的类的私有和保护成员。
  • 通常用于需要两个类之间有非常紧密合作的场景。

声明友元类Person

class Person
{

};

并在Student类中做好定义

friend class Person;

之后便可以在友元类Person中访问Student中的所有成员!

值得注意的是:友元函数允许单个函数访问类的私有成员,而友元类允许整个类的所有成员函数访问另一个类的私有成员。这些机制适用于特殊的场景,如需要在两个类或函数之间紧密协作时使用,但应谨慎使用以避免破坏封装性和增加耦合度。

此处奉上源代码,供大家自行尝试:

#include <iostream>
#include <windows.h>
class Student
{
    public:
    std::string pub_name;
    short pub_age;
    std::string pub_gantal;

    protected:
        long pro_sno;

    
    private:
        long pri_phonenumber;
        std::string pri_address;

    public:
       
       void initPubInfo(std::string pub_name,short pub_age,std::string pub_gantal)
       {
        this->pub_name = pub_name;
        this->pub_age  = pub_age;
        this->pub_gantal = pub_gantal;
       }

       void showPubInfo()
       {
        std::cout<<"name: "<<this->pub_name<<","
                 <<"age: "<<this->pub_age<<","
                 <<"gental: "<<this->pub_gantal<<std::endl;
       }

       void initProInfo(long pro_sno)
       {
        this->pro_sno = pro_sno;
       }

       void showProInfo()
       {
        std::cout<<"student's sno: "<<this->pro_sno<<std::endl;
       }

       void initPriInfo(long pri_phonenumber,std::string pri_address)
       {
        this->pri_phonenumber = pri_phonenumber;
        this->pri_address = pri_address;
       }

       void showPriInfo()
      {
        std::cout<<"phone number: "<<this->pri_phonenumber<<","
        <<"address: "<<this->pri_address<<std::endl;
      }

      friend void doingInfo1(Student& obj)
      {
        obj.pro_sno =1234;
        obj.pri_phonenumber = 18192090902;
        std::cout<<obj.pro_sno<<std::endl;
        std::cout<<obj.pri_phonenumber<<std::endl;
      }
      friend void doingInfo2(Student& obj);

      friend class Person;
};

void doingInfo2(Student& obj)
{
    obj.pri_address = "BeiJing";
    obj.pro_sno=123;
    std::cout<<obj.pri_address<<std::endl;
    std::cout<<obj.pro_sno<<std::endl;
}


class Person
{

    public:
       void showStudent(Student& obj)
       {
        
          
       }

};


  int main()
  {
    #ifdef _WIN32
    // 设置控制台的编码为 UTF-8
    SetConsoleOutputCP(CP_UTF8);
    #endif
    Student* student= new Student();
    


    return 0;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值