天天看點

待補遺(6)[C++]兩個類如何通過友元聲明互相通路對方的非公有成員

1.設有類A,和類B兩個類,假定類A的聲明在類B之前(類的聲明總會有先後之分)

2.類A與類B,各自具有一個private權限的func函數。

一、類A,類B的聲明如下(定義在在同一個源檔案中):

#include <iostream>

class A{
private:
	void func()
	{
		std::cout << "A::func()" << std::endl;
	}
};

class B{
private:
	void func()
	{
		std::cout << "B::func()" << std::endl;
	}
};

int main()
{

	system("pause");
	return 0;
}
           

執行結果:

待補遺(6)[C++]兩個類如何通過友元聲明互相通路對方的非公有成員

二、若類A,有一個成員函數call_func_of_B(B &b)想要調用類B的private成員函數func(),為了

解決這個問題可将call_func_of_B(B &b)函數聲明為類B的友元函數,代碼書寫如下:

#include <iostream>

class B;//由于類B的定義在類A之後,是以用到類B的聲明時,使用前向聲明

class A{
private:
	void func()
	{
		std::cout << "A::func()" << std::endl;
	}
public:
	void call_func_of_B(B &b);//可以使用類B定義指針,引用,對象,因為上文有前向聲明
};

class B{
private:
	void func()
	{
		std::cout << "B::func()" << std::endl;
	}
	friend void A::call_func_of_B(B &b);//友元聲明将類A的成員函數聲明為類B的友元函數
};
//定義類A成員函數
void A::call_func_of_B(B &b)
{
	b.func();
}
           

測試代碼:

int main(){
	A a;
	B b;
	a.call_func_of_B(b);

	system("pause");
	return 0;
}
           

執行結果:

待補遺(6)[C++]兩個類如何通過友元聲明互相通路對方的非公有成員

注意的問題:

1.不能将call_func_of_B()函數的定義放在它聲明的地方,代碼如下:

#include <iostream>

class B;//由于類B的定義在類A之後,是以用到類B的聲明時,使用前向聲明

class A{
private:
	void func()
	{
		std::cout << "A::func()" << std::endl;
	}
public:
	void call_func_of_B(B &b)//可以使用類B定義指針,引用,對象,因為上文有前向聲明
	{
		//b.func();
		//前向聲明能力有限,對于類B的細節,隻有定義之後才能通路
	}
};
           

2.也不能在聲明友元函數是對call_func_of_B()函數進行定義

class B{
private:
	void func()
	{
		std::cout << "B::func()" << std::endl;
	}
	friend void A::call_func_of_B(B &b)//友元聲明将類A的成員函數聲明為類B的友元函數
	{
		//b.func();//C3060 不允許對使用限定名的友元函數進行定義
	}

};
           

對于C3060編譯器錯誤,參見MSDN: http://msdn.microsoft.com/en-us/library/9h84hcy4(v=vs.90).aspx

三、由于類B的定義晚于類A的定義,若要使類B的成員通路類A的非public成員,需将類B設為類A的友元類

#include <iostream>

class B;//由于類B的定義在類A之後,是以用到類B的聲明時,使用前向聲明

class A{
private:
	void func()
	{
		std::cout << "A::func()" << std::endl;
	}
public:
	void call_func_of_B(B &b);//可以使用類B定義指針,引用,對象,因為上文有前向聲明
	friend class B;//此時若要用B的成員函數通路A的非public成員,隻能将類B設為類A的友元類
};

class B{
private:
	void func()
	{
		std::cout << "B::func()" << std::endl;
	}
public:
	void call_func_of_A(A &a);
	friend void A::call_func_of_B(B &b);//友元聲明将類A的成員函數聲明為類B的友元函數
};
void A::call_func_of_B(B &b)
{
	b.func();
}
void B::call_func_of_A(A &a)
{
	a.func();
}


int main()
{
	A a;
	B b;
	a.call_func_of_B(b);
	b.call_func_of_A(a);

	system("pause");
	return 0;
}
           

執行結果:

待補遺(6)[C++]兩個類如何通過友元聲明互相通路對方的非公有成員

1.同樣,類B的成員函數可在類B中定義,也可在類B作用域外定義

class B{
private:
	void func()
	{
		std::cout << "B::func()" << std::endl;
	}
public:
	void call_func_of_A(A &a)
	{
		a.func();
	}

	friend void A::call_func_of_B(B &b);//友元聲明将類A的成員函數聲明為類B的友元函數
};
           

以上代碼,可以執行成功!

繼續閱讀