友元实例:友元类及友元函数
??????? 學習了c++這么久,一直沒有對友元進行了解,據說友元不是特別好用(據說,不是我說的),因此直到今天才去了解。其實友元確實不是很常用,但友元功能確實很實用,它不但能夠釋放類中的非公有成員,同時還能保證了類的封裝性。用戶可以有選擇為具體的類或函數賦予“通行證”。還是比較靈活的。比如:某個類去訪問另一個類的私有成成員,或者一個函數去訪問某個類的私有成員等等,都可以使用友元來實現。
?????? 下面就友元做了兩個小例子,望高手指教。(每段代碼都在不同的文件中)
首先是關于友元類的代碼,就一句話,很簡單。。。
Test.h:
#ifndef TEST_H #define TEST_H#include<iostream> using namespace std;class Test {friend class FriendTest; //此處聲明FriendTest為Test的友元類,FriendTest類可以訪問Test的私有成員public:Test();void set(int h,int w);void print();virtual ~Test();protected:private:int height;int weight; };#endif // TEST_HTest.cpp
#include "../include/Test.h"Test::Test() {//ctorheight = 0;weight = 0; } void Test::set(int h, int w) {height = h;weight = w; } void Test::print() {cout << height << " ";cout << weight <<endl; }Test::~Test() {//dtor }下面關于FriendTest的相關程序。
FriendTest.h
#ifndef FRIENDTEST_H #define FRIENDTEST_H#include "Test.h"class FriendTest {public:FriendTest();void setTest(Test& t, int h, int w); virtual ~FriendTest();protected:private: };#endif // FRIENDTEST_HFriendTest.cpp
#include "../include/FriendTest.h"FriendTest::FriendTest() {//ctor } void FriendTest::setTest(Test& t, int h, int w) //之前聲明了友元,所以此處可以調用私有成員 {t.height = h;t.weight = w; } FriendTest::~FriendTest() {//dtor }#include <iostream> #include "./include/Test.h" #include "./include/FriendTest.h"using namespace std;int main() {Test t;FriendTest ft;t.set(30, 20);ft.setTest(t,9,8);t.print();return 0; }接下來是關于友元函數的問題,友元函數我弄了很久,對于某個類來說,只希望其某個函數為友元,需要對函數進行友元聲明。然而將上邊代碼中的友元類的聲明改成友元函數的聲明,編譯不通過,提示未定義。后來發現對于友元函數來說兩個類必須放在同一個文件中,并且要有部分調整,具體實現如下,并富有詳解。
部分代碼省略。。。主要代碼如下:
#include <iostream> using namespace std; //由于兩個類都使用到了另一個類,所以順序很關鍵。如果將兩個類的順序顛倒會出現編譯不通過,并提示未定義。另外友元函數必須在最后實現,因為它用到了兩個類中的成員。仔細與上一部分的代碼比較,你便會了解里邊的玄機。。。 class Test; //首先需要聲明Test類,FriendTest類中需要使用。 class FriendTest {public:FriendTest();void setTest(Test& t, int h, int w);virtual ~FriendTest();protected:private: }; class Test {friend void FriendTest::setTest(Test& t, int h, int w); //友元函數聲明public:Test();void set(int h,int w);void print();virtual ~Test();protected:private:int height;int weight; };void FriendTest::setTest(Test& t, int h, int w) {t.height = h;t.weight = w; }int main() {cout << "friend" <<endl;Test t;FriendTest ft;t.set(30, 20);ft.setTest(t,9,8);t.print();return 0; }
?另外在網上看到了一個關于primer c++中一個友元例子的講解可能對你理解有些幫助:
????????? 做了部分修改。。。。。。
摘自:http://blog.sina.com.cn/s/blog_4901f88e0100hbym.html
第一種寫法問題:
編譯到Screen時,由于Screen類使用到Window_Mgr的成員函數,前面給出了Window_Mgr的聲明,但不清楚Window_Mgr的完整定義,對成員函數不清楚,所以友元函數聲明不成立,編譯出錯。
class Window_Mgr
class Screen
{
? public:
??? friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);???????
? private:
??? int height;
??? int width;
}
class Window_Mgr
{
public:
? typedef std::string::size_type index;
? Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)
? {
??? s.height += r;
??? s.width += c;
??? return *this;
? }
}
?
第二種寫法問題在于:
編譯到relocate時,由于Screen& s的實現使用到Screen的成員變量,雖然前面給出了Screen的聲明,但此時還不清楚Screen的完整定義,所以編譯出錯。
class?Screen;
class Window_Mgr
{
public:
? typedef std::string::size_type index;
? Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)
? {
??? s.height += r;
??? s.width += c;
??? return *this;
? }
}
class Screen
{
? public:
??? friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);
? private:
??? int height;
??? int width;
}
第三種寫法:
將Window_Mgr::relocate的實現移動到最后,由于編譯類Window_Mgr時,并不需要Screen&s 的實現細節,問題得到解決
class?Screen;
class Window_Mgr
{
public:
? typedef std::string::size_type index;
? Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s);?? //無內部成員的使用
}
class Screen
{
? public:
??? friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);
? private:
??? int height;
??? int width;
}
?
?
? Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s)
? {
??? s.height += r;
??? s.width += c;
??? return *this;
? }
?
可見,這兩個類如果編譯成功需要嚴格的交替順序
這也就解釋了為什么放在兩個文件中無法編譯。
?
附錄:
一開始的實現的不能編譯的兩個文件
實現分別如下:Window_Mgr.h
#ifndef WINDOW_MGR //為了避免兩個文件嵌套
#define WINDOW_MGR
#include <string>
#include <Screen.h>
class Window_Mgr
{
public:
? typedef std::string::size_type index;
? Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)
? {
??? s.height += r;
??? s.width += c;
??? return *this;
? }
}
#endif
Screen.h
#ifndef SCREEN
#define SCREEN
#include "Window_Mgr.h"
class Screen
{
? public:
??? friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);
? private:
??? int height;
??? int width;
}
#endif
?
?
轉載于:https://www.cnblogs.com/javaexam2/archive/2011/11/21/2632880.html
總結
以上是生活随笔為你收集整理的友元实例:友元类及友元函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在eclipse中反编译并查看jar包的
- 下一篇: 无标题窗体的移动及其简单美化