友元类的概念和使用
(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++编译器在寻找运算符函数时,找的自己内部的函数,有就用显示实现的函数,没有的话就使用默认实现的,有元函数是外部函数,就不太编译器寻找范围内
学习记录,侵权联系删除。
来源:朱老师物联网大课堂