下面就友元做了两个小例子,望高手指教。(每段代码都在不同的文件中)
首先是关于友元类的代码,就一句话,很简单。。。
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_H
Test.cpp
- #include "../include/Test.h"
- Test::Test()
- {
- //ctor
- height = 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_H
FriendTest.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
{
}
class Window_Mgr
{
public:
}
第二种写法问题在于:
编译到relocate时,由于Screen& s的实现使用到Screen的成员变量,虽然前面给出了Screen的声明,但此时还不清楚Screen的完整定义,所以编译出错。
class
class Window_Mgr
{
public:
}
class Screen
{
}
第三种写法:
将Window_Mgr::relocate的实现移动到最后,由于编译类Window_Mgr时,并不需要Screen&s 的实现细节,问题得到解决
class
class Window_Mgr
{
public:
}
class Screen
{
}
可见,这两个类如果编译成功需要严格的交替顺序
这也就解释了为什么放在两个文件中无法编译。
附录:
一开始的实现的不能编译的两个文件
实现分别如下:Window_Mgr.h
#ifndef WINDOW_MGR //为了避免两个文件嵌套
#define WINDOW_MGR
#include <string>
#include <Screen.h>
class Window_Mgr
{
public:
}
#endif
Screen.h
#ifndef SCREEN
#define SCREEN
#include "Window_Mgr.h"
class Screen
{
}
#endif