友元破坏了类的封装性,能够让友元的类或函数访问到类的私有数据,既然它有这个特性那就看看怎么使用吧,这里看个友元成员函数的使用。
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
class CDate;
class CTime
{
public:
void showDate(CDate &date)
{
printf("%d-%d-%d \n", date.mYear, date.mMonth, date.mDay);
}
};
class CDate
{
friend void CTime::showDate(CDate &date);
public:
CDate(int y, int m, int d): mYear(y), mMonth(m), mDay(d)
{
}
private:
int mYear;
int mMonth;
int mDay;
};
int main()
{
CDate date(2024, 8, 30);
CTime time;
time.showDate(date);
return 0;
}
看这个代码的意图是想在类 CTime j里通过传进来的 CDate 对象直接访问CDate的私有数据,没有友元的情况下,是无法直接访问类的私有数据的。但这样使用最直接的错误就是找不到 CDate的定义,编译错误如下 :
有人会说不是有个前置声明吗?然而这个 class CDate; 前置声明对声明这个类型的指针是有效的,因为指针的大小是固定的(4字节或8字节),不管定义什么类型的指针其大小都是固定的,它不关心指针指向的具体的数据类型。但非指针定义就需要知道这个类型的具体结构,因为为分配相应的内存大小。以下改成指针类型的,但也不能访问数据,只是能编译成功而已:
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
class CDate;
class CTime
{
public:
void showDate(CDate *date)
{
//printf("%d-%d-%d \n", date.mYear, date.mMonth, date.mDay);
}
};
class CDate
{
friend void CTime::showDate(CDate *date);
public:
CDate(int y, int m, int d): mYear(y), mMonth(m), mDay(d)
{
}
private:
int mYear;
int mMonth;
int mDay;
};
int main()
{
CDate date(2024, 8, 30);
CTime time;
time.showDate(&date);
return 0;
}
那怎么解决上面的问题呢?那就是那个友元成员函数只在类里声明,在类外定义即可。如:
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
class CDate;
class CTime
{
public:
void showDate(CDate &date);
};
class CDate
{
friend void CTime::showDate(CDate &date);
public:
CDate(int y, int m, int d): mYear(y), mMonth(m), mDay(d)
{
}
private:
int mYear;
int mMonth;
int mDay;
};
void CTime::showDate(CDate &date)
{
printf("%d-%d-%d \n", date.mYear, date.mMonth, date.mDay);
}
int main()
{
CDate date(2024, 8, 30);
CTime time;
time.showDate(date);
return 0;
}
编译器毕竟是从上到下进行编译,到编译 void CTime::showDate(CDate &date) 时,已经有了 CDate 的定义了,所以编译器知道这个 CDate 的大小及数据结构。