public, private, protected, friend

本文详细介绍了C++中的三种权限修饰符(public、private、protected)以及它们在类成员和继承关系中的应用,同时讨论了friend关键字的使用,展示了权限管理在类内部和外部的不同影响。

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

权限管理是 c++ 的一大特点,面向对象语言封装的特性也给权限管理带了了方便。c++ 中的权限主要有3种:public,private,protected。类中的函数和属性默认是private的,类的继承关系默认也是private的。

public,private,protected 的使用场景有两个:修饰类成员以及修饰类的继承关系。本文先记录这 3个权限修饰符修饰类成员以及继承关系,最后再记录friend的使用。

1 类成员

类内部子类内部通过对象
public可以访问可以访问可以访问
private可以访问不可以访问不可以访问
protected可以访问可以访问不可以访问

1.1 public

public权限是最宽松的,被修饰为public的成员在类内部可以直接访问,也可以在类外部通过对象来访问,当然也可以在类的派生类中访问,权限没有限制。

下边的代码, Base类中的Do函数是public的,属性a_是public的,这两个方法和属性在类内部,子类中,类外部都可以访问。

最宽松的权限管理,没有什么限制。

#include <iostream>
#include <string>

class Base {
public:
  Base(int a) {
   a_ = a;
   std::cout << "Base(), a_ = " << a_ << std::endl;
   Do();
  };

  ~Base() {
    std::cout << "~Base(), a_ = " << a_ << std::endl;
  };

  void Do() {
    std::cout << "Base() Do(), a_ = " << a_ << std::endl;
  };

public:
  int a_;
};

class Derived : public Base {
public:
  Derived() : Base(50) {
    a_ = 100;
    std::cout << "Derived(), a_ = " << a_ << std::endl;
  };

  ~Derived() {
    std::cout << "~Derived(), a_ = " << a_ << std::endl;
  };
};

int main() {
  Base b(1);
  b.Do();

  Derived d;
  d.Do();

  b.a_ = 12;
  b.Do();

  d.a_ = 20;
  d.Do();
  return 0;
}

1.2 private

如下代码,将Base中的Do函数,以及属性a_的权限改成了private。private权限的函数或者属性只能在类内部访问,不能在类外部访问,在子类中也不能访问。

最严格的管理,最隐秘的隐私,自己的孩子都不知道,外人当然不知道。

技术来源于生活。

#include <iostream>
#include <string>

class Base {
public:
  Base(int a) {
   a_ = a;
   std::cout << "Base(), a_ = " << a_ << std::endl;
   Do();
  };

  ~Base() {
    std::cout << "~Base(), a_ = " << a_ << std::endl;
  };

private:
  void Do() {
    std::cout << "Base() Do(), a_ = " << a_ << std::endl;
  };

private:
  int a_;
};

class Derived : public Base {
public:
  Derived() : Base(50) {
    a_ = 100; // 编译错误,private 属性只能在类内部访问,子类不能方位
    std::cout << "Derived(), a_ = " << a_ << std::endl; // 编译错误
  };

  ~Derived() {
    std::cout << "~Derived(), a_ = " << a_ << std::endl; // 编译错误
  };
};

int main() {
  Base b(1);
  b.Do(); // 编译错误

  Derived d;
  d.Do(); // 编译错误

  b.a_ = 12; // 编译错误
  b.Do(); // 编译错误

  d.a_ = 20; // 编译错误
  d.Do(); // 编译错误
  return 0;
}

1.3 protected

protected权限管理介于public和private之间。protected权限的函数或者属性在类内部能访问,在派生类的内部也能访问,但是在类外部通过对象不能访问。

#include <iostream>
#include <string>

class Base {
public:
  Base(int a) {
   a_ = a;
   std::cout << "Base(), a_ = " << a_ << std::endl;
   Do();
  };

  ~Base() {
    std::cout << "~Base(), a_ = " << a_ << std::endl;
  };

protected:
  void Do() {
    std::cout << "Base() Do(), a_ = " << a_ << std::endl;
  };

protected:
  int a_;
};

class Derived : public Base {
public:
  Derived() : Base(50) {
    a_ = 100;
    std::cout << "Derived(), a_ = " << a_ << std::endl;
    Do();
  };

  ~Derived() {
    std::cout << "~Derived(), a_ = " << a_ << std::endl;
  };
};

int main() {
  Base b(1);
  b.Do(); // 编译错误

  Derived d;
  d.Do(); // 编译错误

  b.a_ = 12; // 编译错误
  b.Do(); // 编译错误

  d.a_ = 20; // 编译错误
  d.Do(); // 编译错误
  return 0;
}

2 继承

在类继承的时候,如果不指定权限,默认是private继承。

基类 public 成员基类private成员基类protected成员
public 继承在子类中仍为 public在子类中不可见在子类中仍为 protected
private 继承在子类中变为 private在子类中不可见在子类中变为 private
protected 继承在子类中变为 protected在子类中不可见在子类中仍为 protected

2.1 public

publi 继承,在子类中能访问父类的protected成员,但是不能访问private成员。

在类外边通过对象,也不能访问protected成员和private成员。

#include <iostream>
#include <string>

class Base {
public:
  Base() {
    std::cout << "Base()" << std::endl;
  };

  ~Base() {
    std::cout << "~Base()" << std::endl;
  };

  void PublicDo() {
    std::cout << "Base() public do" << std::endl;
  }

  int public_a_;

private:
  void PrivateDo() {
    std::cout << "Base() private do" << std::endl;
  }

  int private_a_;

protected:
  void ProtectedDo() {
    std::cout << "Base() protected do" << std::endl;
  }

  int protected_a_;
};

class Derived : public Base {
public:
  Derived() {
    std::cout << "Derived()" << std::endl;
    std::cout << "public a: " << public_a_ << std::endl;
    std::cout << "private a: " << private_a_ << std::endl; // 编译错误
  }

  ~Derived() {
    std::cout << "~Derived()" << std::endl;
  }

  void DerivedDo() {
    PublicDo();
    PrivateDo(); // 编译错误
    ProtectedDo();
  }
};

int main() {
  Base b;
  b.PublicDo();
  b.PrivateDo(); // 编译错误
  b.ProtectedDo(); // 编译错误

  b.public_a_ = 10;
  b.private_do_ = 20; // 编译错误
  b.protected_do_ = 30; // 编译错误

  Derived d;
  d.DerivedDo();
  return 0;
}

2.2 private

private继承,父类的public成员和 protected 成员在子类中都成为private属性,在子类内可以访问,不能通过对象来访问,子类再派生的类也不能访问;子类中不能访问父类中的private成员。 

#include <iostream>
#include <string>

class Base {
public:
  Base() {
    std::cout << "Base()" << std::endl;
  };

  ~Base() {
    std::cout << "~Base()" << std::endl;
  };

  void PublicDo() {
    std::cout << "Base() public do" << std::endl;
  }

  int public_a_;

private:
  void PrivateDo() {
    std::cout << "Base() private do" << std::endl;
  }

  int private_a_;

protected:
  void ProtectedDo() {
    std::cout << "Base() protected do" << std::endl;
  }

  int protected_a_;
};

class Derived : private Base {
public:
  Derived() {
    std::cout << "Derived()" << std::endl;
    std::cout << "public a: " << public_a_ << std::endl;
    // std::cout << "private a: " << private_a_ << std::endl; // 编译错误
  }

  ~Derived() {
    std::cout << "~Derived()" << std::endl;
  }

  void DerivedDo() {
    PublicDo();
    // PrivateDo(); // 编译错误
    ProtectedDo();
  }
};

int main() {
  Base b;
  b.PublicDo();
  // b.PrivateDo(); // 编译错误
  // b.ProtectedDo(); // 编译错误

  b.public_a_ = 10;
  // b.private_do_ = 20; // 编译错误
  // b.protected_do_ = 30; // 编译错误

  Derived d;
  d.DerivedDo();
  return 0;
}

2.3 protected

父类中的public成员,在子类中变为protected属性;protected和private属性保持不变

#include <iostream>
#include <string>

class Base {
public:
  Base() {
    std::cout << "Base()" << std::endl;
  };

  ~Base() {
    std::cout << "~Base()" << std::endl;
  };

  void PublicDo() {
    std::cout << "Base() public do" << std::endl;
  }

  int public_a_;

private:
  void PrivateDo() {
    std::cout << "Base() private do" << std::endl;
  }

  int private_a_;

protected:
  void ProtectedDo() {
    std::cout << "Base() protected do" << std::endl;
  }

  int protected_a_;
};

class Derived : protected Base {
public:
  Derived() {
    std::cout << "Derived()" << std::endl;
    std::cout << "public a: " << public_a_ << std::endl;
    std::cout << "private a: " << private_a_ << std::endl; // 编译错误
  }

  ~Derived() {
    std::cout << "~Derived()" << std::endl;
  }

  void DerivedDo() {
    PublicDo();
    PrivateDo(); // 编译错误
    ProtectedDo();
  }
};

int main() {
  Base b;
  b.PublicDo();
  b.PrivateDo(); // 编译错误
  b.ProtectedDo(); // 编译错误

  b.public_a_ = 10;
  b.private_do_ = 20; // 编译错误
  b.protected_do_ = 30; // 编译错误

  Derived d;
  d.DerivedDo();
  return 0;
}

3 friend

friend 是说一个类对另一个函数或者另一个类的认证,如果一个类 A 中认证一个不是 A 成员函数的函数 F 为 friend 或者另一个类 B 为 friend,那么 F 或者 B 都可以访问 A 的私有成员。

给固化的权限管理增加了一些灵活性。

friend,朋友,可以访问私有成员;而自己的子类却不能访问私有成员。朋友的关系,比父子之间的关系还要近。

  

3.1 友元函数

(1)友元函数可以访问类的 public 成员,private 成员,protected 成员

(2) 友元函数可以声明在类的 public 中,private 中,protected 中,如代码中的 PhoneTest,PhoneTest1,PhoneTest2,效果是一样的

(3)友元函数可以是一个独立的函数,也可以定义在类中(其实不属于类),也可以是另一个类的成员函数

#include <iostream>
#include <string>

class Phone;
class Work {
public:
  void Do(Phone phone);
};

class Phone {
public:
  Phone() {
    std::cout << "Phone()" << std::endl;
  }

  ~Phone() {
    std::cout << "~Phone()" << std::endl;
  }

  void PublicCallUp() {
    std::cout << "PublicCallUp()" << std::endl;
  }

  int public_a_ = 10;

  friend void PhoneTest(Phone phone);
  friend void Work::Do(Phone phone);
  friend void InnerFriend(Phone phone) {
    std::cout << "InnerFriend()" << std::endl;
    phone.Print();

    phone.PublicCallUp();
    phone.PrivateCallUp();
    phone.ProtectedCallUp();

    phone.public_a_ = 11;
    phone.private_a_ = 21;
    phone.protected_a_ = 31;
    phone.Print();
  }

private:
  void PrivateCallUp() {
    std::cout << "PrivateCallUp)" << std::endl;
  }

  void Print() {
    std::cout << "public a: " << public_a_ << std::endl;
    std::cout << "private a: " << private_a_ << std::endl;
    std::cout << "protected a: " << protected_a_ << std::endl;
  }

  int private_a_ = 20;

  friend void PhoneTest1(Phone phone);

protected:
  void ProtectedCallUp() {
    std::cout << "ProtectedCallUp()" << std::endl;
  }

  int protected_a_ = 30;

  friend void PhoneTest2(Phone phone);
};

  void Work::Do(Phone phone) {
    std::cout << "Work() Do()" << std::endl;
    phone.Print();

    phone.PublicCallUp();
    phone.PrivateCallUp();
    phone.ProtectedCallUp();

    phone.public_a_ = 11;
    phone.private_a_ = 21;
    phone.protected_a_ = 31;
    phone.Print();
  }


void PhoneTest(Phone phone) {
  std::cout << "PhoneTest" << std::endl;
  phone.Print();

  phone.PublicCallUp();
  phone.PrivateCallUp();
  phone.ProtectedCallUp();

  phone.public_a_ = 11;
  phone.private_a_ = 21;
  phone.protected_a_ = 31;
  phone.Print();
}

void PhoneTest1(Phone phone) {
  std::cout << "PhoneTest1" << std::endl;
  phone.Print();

  phone.PublicCallUp();
  phone.PrivateCallUp();
  phone.ProtectedCallUp();

  phone.public_a_ = 11;
  phone.private_a_ = 21;
  phone.protected_a_ = 31;
  phone.Print();
}

void PhoneTest2(Phone phone) {
  std::cout << "PhoneTest2" << std::endl;
  phone.Print();

  phone.PublicCallUp();
  phone.PrivateCallUp();
  phone.ProtectedCallUp();

  phone.public_a_ = 11;
  phone.private_a_ = 21;
  phone.protected_a_ = 31;
  phone.Print();
}

int main() {
  Phone phone;
  PhoneTest(phone);
  PhoneTest1(phone);
  PhoneTest2(phone);

  Work work;
  work.Do(phone);
  return 0;
}

3.2 友元类

友元类中的函数,不管是 public,还是 private 还是 protected 的,都可以访问类的成员(public,private,protected)。 

#include <iostream>
#include <string>

class Phone;
class Work {
public:
  void PublicDo(Phone phone);

private:
  void PrivateDo(Phone phone);

protected:
  void ProtectedDo(Phone phone);
};

class Phone {
public:
  Phone() {
    std::cout << "Phone()" << std::endl;
  }

  ~Phone() {
    std::cout << "~Phone()" << std::endl;
  }

  void PublicCallUp() {
    std::cout << "PublicCallUp()" << std::endl;
  }

  int public_a_ = 10;

  friend class Work;

private:
  void PrivateCallUp() {
    std::cout << "PrivateCallUp)" << std::endl;
  }

  void Print() {
    std::cout << "public a: " << public_a_ << std::endl;
    std::cout << "private a: " << private_a_ << std::endl;
    std::cout << "protected a: " << protected_a_ << std::endl;
  }

  int private_a_ = 20;

protected:
  void ProtectedCallUp() {
    std::cout << "ProtectedCallUp()" << std::endl;
  }

  int protected_a_ = 30;

};

void Work::PublicDo(Phone phone) {
    std::cout << "Work() PublicDo()" << std::endl;
    phone.Print();

    phone.PublicCallUp();
    phone.PrivateCallUp();
    phone.ProtectedCallUp();

    phone.public_a_ = 11;
    phone.private_a_ = 21;
    phone.protected_a_ = 31;
    phone.Print();

    PrivateDo(phone);
    ProtectedDo(phone);
}

void Work::PrivateDo(Phone phone) {
    std::cout << "Work() PrivateDo()" << std::endl;
    phone.Print();

    phone.PublicCallUp();
    phone.PrivateCallUp();
    phone.ProtectedCallUp();

    phone.public_a_ = 11;
    phone.private_a_ = 21;
    phone.protected_a_ = 31;
    phone.Print();
}

void Work::ProtectedDo(Phone phone) {
    std::cout << "Work() ProtectedDo()" << std::endl;
    phone.Print();

    phone.PublicCallUp();
    phone.PrivateCallUp();
    phone.ProtectedCallUp();

    phone.public_a_ = 11;
    phone.private_a_ = 21;
    phone.protected_a_ = 31;
    phone.Print();
}

int main() {
  Phone phone;

  Work work;
  work.PublicDo(phone);
  // work.PrivateDo(phone);
  // work.ProtectedDo(phone);
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值