引言
封装是对象的一大特征,它可以选择性的对外暴露属性和方法。但是有没有一种方式可以把自己的内部属性暴露给指定的函数、方法或者类呢?答案是肯定的,那就是友元。网络上大部分文章介绍的都是在同一个文件中使用友元,而本文章将示例分在不同文件中进行介绍。
友元函数 parent.hpp
头文件中声明了类 Parent
,它有两个属性,分别是公开的 username
及私有的 age
。同时声明了带参构造函数及打印基础信息的成员方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #ifndef CPPDEMO_PARENT_H #define CPPDEMO_PARENT_H #include <string> class Parent { public : std::string username; private : int age; public : Parent (std::string username, int age); void print_info () const ; }; #endif
以下 parent.cpp
是具体的实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include <utility> #include "parent.hpp" using namespace std;Parent::Parent (std::string username, int age) { this ->username = std::move (username); this ->age = age; } void Parent::print_info () const { cout << "username is : " << this ->username << " age is : " << this ->age << endl; }
以下的 main.cpp
是我们的测试类:
1 2 3 4 5 6 7 8 #include "parent.hpp" int main () { Parent p ("father" , 38 ) ; p.print_info (); return 0 ; }
控制台输出本对象的基础信息:
1 # username is : father age is : 38
我们知道,age
是 Parent
比较私密的属性,毕竟谁也不想把自己的年龄告诉其他人,除非把自己的信息通过某种特殊的途径对外告知,比如:资料卡。
我们在类 Parent
中添加传递信息的资料卡函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #ifndef CPPDEMO_PARENT_H #define CPPDEMO_PARENT_H #include <string> class Parent { friend void card (Parent &) ; public : std::string username; private : int age; public : Parent (std::string username, int age); void print_info () const ; }; #endif
我们在 main.cpp
中添加对 void card(Parent &)
函数的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include "parent.hpp" using namespace std;void card (Parent &parent) { cout << "others get the username: " << parent.username << " and age is : " << parent.age << endl; } int main () { Parent p ("father" , 38 ) ; card (p); return 0 ; }
控制台得到以下输出:
1 # others get the username: father and age is : 38
外部通过 card
方法拿到了 Parent
类中的私有字段 age
。
友元类 作为父母,肯定愿意把自己的“一切”告诉孩子!所以我们改造类 Parent
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #ifndef CPPDEMO_PARENT_H #define CPPDEMO_PARENT_H #include <string> class Parent { friend class Child ; public : std::string username; private : int age; public : Parent (std::string username, int age); void print_info () const ; }; #endif
接着我们定义 Child
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #ifndef CPPDEMO_CHILD_H #define CPPDEMO_CHILD_H class Parent ;class Child { private : Parent *parent; public : explicit Child (Parent *parent) ; void parent_info () ; }; #endif
Child
类的实现为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include "child.hpp" #include "parent.hpp" using namespace std;Child::Child (Parent *parent) : parent (parent) { } void Child::parent_info () { std::cout << "child get the parent info username is : " << this ->parent->username << " age is : " << this ->parent->age << endl; }
main.cpp
进行测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 #include "parent.hpp" #include "child.hpp" using namespace std;int main () { Parent p ("father" , 38 ) ; Child child (&p) ; child.parent_info (); return 0 ; }
输出:
1 # child get the parent info username is : father age is : 38
成员友元函数 如果把类变成友元类,那么友元类中的所有方法都能访问私有属性了。那么如何限制指定的方法访问呢?此时就需要成员友元函数了。
改造 Parent
类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #ifndef CPPDEMO_PARENT_H #define CPPDEMO_PARENT_H #include <string> #include "child.hpp" class Parent { friend void Child::parent_info () ; public : std::string username; private : int age; public : Parent (std::string username, int age); void print_info () const ; }; #endif
Child
类新增 all_parent_info
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> #include "child.hpp" #include "parent.hpp" using namespace std;Child::Child (Parent *parent) : parent (parent) { } void Child::parent_info () { std::cout << "child get the parent info username is : " << this ->parent->username << " age is : " << this ->parent->age << endl; } void Child::all_parent_info () { std::cout << "child get the parent info username is : " << this ->parent->username << " age is : " << this ->parent->age << endl; }
我们运行一下看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 #include "parent.hpp" #include "child.hpp" using namespace std;int main () { Parent p ("father" , 38 ) ; Child child (&p) ; child.parent_info (); child.all_parent_info (); return 0 ; }
得到以下输出:
1 2 3 4 5 # /Users/tubetrue01/CLionProjects/cppDemo/child.cpp:24:71: error: 'age' is a private member of 'Parent' this->parent->username << " age is : " << this->parent->age << endl; ^ # /Users/tubetrue01/CLionProjects/cppDemo/parent.hpp:19:9: note: declared private here int age;
由此说明 all_parent_info()
方法并不具备访问私有属性的权限。