
【C++】友元类和友元函数
AI-摘要
Tianli GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客
友元 friend
1. private 修饰成员问题
private 修饰成员内容,有且只能在类内使用,类外和子类都无法使用。成员函数如果是 private 修饰,通常情况下是内置函数或者辅助函数。成员变量 private 修饰,通常是为了限制当前成员变量的外部操作方式,降低错误使用的概率。
【private 修饰的成员内容类外操作受限】
2. friend 友元函数
2.1 单一类友元函数
#include <iostream>
using namespace std;
template <typename K, typename V>
class Data
{
public:
Data() {};
Data(K key, V value) : key(key), value(value) {}
Data(const Data &data) : key(data.key), value(data.value) {}
~Data() {}
void set_key(K key) { this->key = key; }
K get_key() { return key; }
void set_value(V value) { this->value = value; }
V get_value() { return value; }
/*
当前 show_data 函数是一个友元函数,使用 friend 关键字修饰
当前函数所需参数类型为 Data<K, V>,根据带有模版类的数据类型
分析
当前函数限制参数外部类型为 Data 类型
内部类型尚未做任何的限制。模版对应类型由提供的实际参数
Data 对应模版类型决定。
【注意】
友元函数有且只在类内定义,告知编译器,当前函数是哪一个类
的友元函数,实现在类外部。
并且,友元函数不属于任何一个类。
【问题】
friend void show_data(const Data<K, V> &data);
当前 show_data 函数使用的模版是 Data 类声明的模版
因为 show_data 不属于 Data 类内,在外部进行函数实现
时,对应的模版 K V 无法再次使用。
【解决】
函数自行声明模版需求。
函数自行定义模版需求对应 K1 和 V1,和当前 Data 类型
模版没有任何的相关性。
*/
template <typename K1, typename V1>
friend void show_data(const Data<K1, V1> &data);
private:
K key;
V value;
};
template <typename K1, typename V1>
void show_data(const Data<K1, V1> &data)
{
/*
因为 show_data 是 Data 类型的友元函数,所以
Data 类型认为 show_data 是自己的朋友,会对朋友
开放整个类的所有权限。
可以通过参数 Data 引用直接操作类内的所有成员内容,包括
private 和 protected 限制的类外无法访问内容。
*/
cout << "Key : " << data.key
<< ", Value : " << data.value
<< endl;
}
int main(int argc, char const *argv[])
{
Data<string, int> data("煎饼果子", 10);
cout << "Key : " << data.get_key()
<< ", Value : " << data.get_value()
<< endl;
show_data(data);
return 0;
}
2.2 多类友元函数
#include <iostream>
using namespace std;
/*
前置声明,告知编译器,当前 Type_B 类存在,可以优先编译使用
后续内容存在 Type_B 类相关内容。
之所以需要完成对应的前置声明操作,是因为在 Type_A 类中,使用了
后续类型 Type_B,数据类型前置声明手段。
*/
class Type_B;
class Type_A
{
public:
Type_A() {}
Type_A(int test_a) : test_a(test_a) {}
Type_A(const Type_A &t) : test_a(t.test_a) {}
friend void show_data(Type_A &t1, Type_B &t2);
private:
int test_a;
};
class Type_B
{
public:
Type_B() {}
Type_B(int test_b) : test_b(test_b) {}
Type_B(const Type_B &t) : test_b(t.test_b) {}
friend void show_data(Type_A &t1, Type_B &t2);
private:
int test_b;
};
void show_data(Type_A &t1, Type_B &t2)
{
cout << "Type_A : " << t1.test_a
<< ", Type_B : " << t2.test_b
<< endl;
}
int main(int argc, char const *argv[])
{
Type_A ta(10);
Type_B tb(200);
show_data(ta, tb);
return 0;
}
3. 友元类
3.1 单向友元
A 类是 B 类的友元类,B 类对 A 类开放所有的成员内。
#include <iostream>
using namespace std;
class Type_B;
class Type_A
{
public:
/*
void show_type_b(Type_B &tb)
{
cout << "MSG : " << tb.msg << endl;
tb.test();
}
如果按照当前代码进行编译操作,编译器提示
03-单向友元类.cpp: In member function ‘void Type_A::show_type_b(Type_B&)’:
03-单向友元类.cpp:13:29: error: invalid use of incomplete type ‘class Type_B’
cout << "MSG : " << tb.msg << endl;
【解释】
当前代码中,确实完成 Type_B 类型前置声明,但是对于编译器而言 Type_B 是一个尚未
完成的类型。但是 show_type_b 函数内部,需要完成对于 Type_B 类型的内容使用。在
当前阶段,无法实现,所以语法报错
【解决】
按照开发的基本要求,声明和实现为分离状态 show_type_b 函数在整个 Type_B 类明确
完成声明的情况下,才可以实现对应的函数,将函数实现放在 Type_B 声明,完成之后。
*/
void show_type_b(Type_B &tb);
};
class Type_B
{
public:
Type_B() {}
Type_B(string msg) : msg(msg) {}
Type_B(const Type_B &tb) : msg(tb.msg) {}
~Type_B() {}
/*
在当前 Type_B 类中,声明了 Type_A 是当前类的友元类
Type_B 对 Type_A 开放所有内容
*/
friend class Type_A;
private:
string msg;
void test()
{
cout << "Hi~ o(* ̄▽ ̄*)ブ,朋友~~~" << endl;
}
};
void Type_A::show_type_b(Type_B &tb)
{
cout << "MSG : " << tb.msg << endl;
tb.test();
}
int main(int argc, char const *argv[])
{
Type_B tb("回答我!");
Type_A ta;
ta.show_type_b(tb);
return 0;
}
3.2 双向友元自行研究
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载必须注明来自 卡卡罗特
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果