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

发布于:2024-03-01 ⋅ 阅读:(81) ⋅ 点赞:(0)

权限管理是 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;
}
本文含有隐藏内容,请 开通VIP 后查看

微信公众号

今日签到

点亮在社区的每一天
去签到