首页 > 代码库 > 友元在继承和传递中的一些问题

友元在继承和传递中的一些问题

声明:①友元关系不能被继承和传递,基类的友元对派生类没有特殊的访问权限,派生类中的友元更不能访问基类中的成员。

           ②友元不是成员函数,所以不能使用作用域解析符来指出要使用哪个函数。这个问题的解决方法是使用强制类型转换,以便匹配原型时能够选择正确地函数。

           ③基类的友元能够访问派生类中的基类成分,这是由于自动将派生类转化成了基类,不是因为继承,但是不能访问派生类的非基类成员。

下面通过例子对这几个问题一一说明。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
class baseDMA;
class hasDMA;
ostream& operator<<(ostream& os,const baseDMA& rs);
ostream& operator<<(ostream& os,const hasDMA& rs);
void fun(const hasDMA& hr);
class baseDMA
{
	friend ostream& operator<<(ostream& os,const baseDMA& rs);
	friend void fun(const hasDMA& hr);
public:
	baseDMA(const char* l="null",int r=0)
	{
		label = new char[strlen(l)+1];
		strcpy(label,l);
		rating = r;
	}
	virtual ~baseDMA()
	{
		delete [] label;
	}
private:
	char* label;
	int rating;
};
class hasDMA:public baseDMA
{
	friend ostream& operator<<(ostream& os,const hasDMA& rs);
public:
	hasDMA(const char* s="none",const char* l="null",int r=0)
		:baseDMA(l,r)
	{
		style = new char[strlen(s)+1];
		strcpy(style,s);
	}
	~hasDMA()
	{
		delete [] style;
	}
private:
	char* style;
};

ostream& operator<<(ostream& os,const baseDMA& rs)
{
	os << "Label: " << rs.label << endl;
	os << "Rating: " << rs.rating << endl;
	return os;
}

ostream& operator<<(ostream& os,const hasDMA& rs)
{
	//os << "Label: " << rs.label << endl;//(一)
	//os << "Rating: " << rs.rating << endl;//(二)
	os << (const baseDMA&)rs;//(三)
	os << "Style: " << rs.style << endl;
	return os;
}

void fun(const hasDMA& hr)
{
	//cout << hr.style << endl;//(四)
	cout << hr.label << endl;//(五)
}

class A   
{   
    int a;   
public:   
    A(int x=0) { a=x; }   
    friend class B;   
};   
  
class B   
{   
public:   
    void fun(A& ob) { cout << ob.a << endl; }  
    friend class C;  
};  
  
class C  
{  
public:  
    //void fun(A& ob) { cout << ob.a << endl; } (六)
};  


void main( void )
{
	baseDMA shirt("port",8);
	hasDMA map("mer","buf",5);
	cout << shirt << endl;
	cout << map << endl;
}

由(一)和(二)两条语句可知,派生类中的友元是不能访问基类中的成员的。

由语句(三)可知我们有一种方法,就是通过强制类型转换将派生类转换成基类,然后使用基类中的友元函数。

由语句(四)和(五)可知,基类中的友元不能访问派生类中的非基类成员,但是能访问派生类中的基类成员,这是通过自动将派生类转化成基类来实现的。

由(六)可知,友元不具有传递性,B是A的友元,C是B的友元,不能得到C是A的友元,所以C不能访问A中的数据。

我在这里所说的友元既包括友元类,也包括友元函数,在继承和传递的问题上两者是保持一致的。