自学内容网 自学内容网

C++ :友元类

友元类的概念和使用

(1)将类A声明为B中的friend class后,则A中所有成员函数都成为类B的友元函数了
(2)代码实战:友元类的定义和使用友元类是单向的
(3)友元类是单向的,代码实战验证

互为友元类

(1)2个类可以互为友元类,代码实战验证
(2)互为友元类要注意互相引用的细节规则

(1)友元类其实就是批量制造友元函数
(2)友元类中所有全部成员都成为了友元函数,相当于一次打了很多洞,极大破坏了面向对象
(3)除非确实有必要,否则建议按需定义友元函数,尽量维护面向对象,让代码更安全健壮

#include <iostream>
#include <string>

class Country;  // Forward declaration of Country

// External friend function declaration
void disp_info_external(const Country &ct);

class InfoDisplayer {
 public:
  // Member function declaration
  void disp_info_member(const Country &ct) const;
};

class InfoFriendClass {
 public:
  // Member function to display information
  void display(const Country &ct) const;
};

class Country {
 private:
  std::string privateName;

 protected:
  int protectedPopulation;

 public:
  std::string publicCapital;

  // Constructor
  Country(std::string name, int population, std::string capital)
      : privateName(name),
        protectedPopulation(population),
        publicCapital(capital) {}

  // Friend function declaration
  friend void disp_info_external(const Country &ct);
  // friend void InfoDisplayer::disp_info_member(const Country &ct);//error: no
  // declaration matches ‘void InfoDisplayer::disp_info_member(const Country&)’
  friend class InfoFriendClass;  // Friend class declaration
};

// Definition of the external friend function
void disp_info_external(const Country &ct) {
  std::cout << "disp_info_external Name: " << ct.privateName << "\n";
  std::cout << "disp_info_external Population: " << ct.protectedPopulation
            << "\n";
  std::cout << "disp_info_external Capital: " << ct.publicCapital << "\n";
}

// Definition of the member friend function
void InfoDisplayer::disp_info_member(const Country &ct) const {
  // std::cout << "disp_info_member Name: " << ct.privateName << "\n";

  // error: ‘int Country::protectedPopulation’ is protected within this context
  //  std::cout << "disp_info_member Population: " << ct.protectedPopulation <<
  //  "\n"; std::cout << "disp_info_member Capital: " << ct.publicCapital <<
  //  "\n";
}

// Definition of the friend class member function
void InfoFriendClass::display(const Country &ct) const {
  std::cout << "InfoFriendClass Name: " << ct.privateName << "\n";
  std::cout << "InfoFriendClass Population: " << ct.protectedPopulation << "\n";
  std::cout << "InfoFriendClass Capital: " << ct.publicCapital << "\n";
}

int test070401() {
  // Create an object of Country
  Country myCountry("Wonderland", 5000000, "Magic City");

  // Display information using the external friend function
  disp_info_external(myCountry);

  // Create an object of InfoDisplayer
  InfoDisplayer displayer;

  // Display information using the member friend function
  displayer.disp_info_member(myCountry);

  // Create an object of InfoFriendClass
  InfoFriendClass friendClass;

  // Display information using the friend class member function
  friendClass.display(myCountry);

  return 0;
}

在这里插入图片描述

#include <iostream>
#include <string>

class Vegetable;  // Forward declaration of Vegetable

class Fruit {
 private:
  std::string name;

 protected:
  std::string color;

 public:
  // Constructor
  Fruit(std::string n, std::string c) : name(n), color(c) {}

  // Friend class declaration
  friend class Vegetable;

  // Definition of the friend function
  void displayVegetable(const Vegetable &veg);
};

class Vegetable {
 private:
  std::string name;

 protected:
  std::string color;

 public:
  // Constructor
  Vegetable(std::string n, std::string c) : name(n), color(c) {}

  // Friend class declaration
  friend class Fruit;

  // Member function declaration
  void displayFruit(const Fruit &fruit) const {
    std::cout << "Vegetable accessing Fruit's name: " << fruit.name << "\n";
    std::cout << "Vegetable accessing Fruit's color: " << fruit.color << "\n";
  }
};

void Fruit::displayVegetable(const Vegetable &veg) {
  std::cout << "Fruit accessing Vegetable's name: " << veg.name << "\n";
  std::cout << "Fruit accessing Vegetable's color: " << veg.color << "\n";
}

int test070402() {
  // Create objects of Fruit and Vegetable
  Fruit apple("Apple", "Red");
  Vegetable spinach("Spinach", "Green");


  apple.displayVegetable(spinach);

  // Display information using the member function of Vegetable
  spinach.displayFruit(apple);

  return 0;
}

在这里插入图片描述

为什么会有友元函数

使用友元函数的优缺点
(1)缺点:破坏了封装机制,尽量不使用友元函数,不得已才使用友元函数
(2)优点:在实现类之间数据共享时,减少系统开销,提高效率。

使用友元函数的两种情况
(1)运算符重载的某些场合需要使用友元
(2)两个类要共享数据的时候
两个类如何共享数据
(1)类内的数据,其实就是类的成员变量
(2)2个类共享数据方法1:将共享数据访问权限设置为public。
(3)2个类共享数据方法2:通过第三个专门封装数据的类,和2个类中带参数的成员函数来传参共享
(4)2个类共享数据方法3:通过友元函数打洞

友元函数和类的成员函数的区别
(1)成员函数有this指针,而友元函数没有this指针。为什么?因为友元只是朋友,并不是类内“自家人”
(2)友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友。
(3)友元关系不具有传递性。类B是类A的友元,类C是B的友元,类C不一定是类A的友元,要看类中是否有相应的声明

共有友元函数
(1)1个函数同时成为2个类的友元函数
(2)共有友元函数可以是外部函数,也可以是某个(第3个)类的成员函数
(3)共有友元函数内可同时访问2个类的受保护成员,间接将2个完全无关的类的数据打通了

总结

有元函数是单向的
两个类可以互为有元类、可以相互拥有有元方法
C++编译器在寻找运算符函数时,找的自己内部的函数,有就用显示实现的函数,没有的话就使用默认实现的,有元函数是外部函数,就不太编译器寻找范围内

学习记录,侵权联系删除。
来源:朱老师物联网大课堂


原文地址:https://blog.csdn.net/qq_43441284/article/details/140422473

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!