[c++] public, private, protected, friend

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

权限管理是 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

public 继承,在子类中能访问父类的 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 的私有成员。

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

  

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;
}
  • 30
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值