什么是友元成员函数?很多时候没有必要把一个类声明为另一个类的友元类,因为后一个类已经提供了很多public接口,前一个类可以直接用,只是在前一个类的某些成员函数中需要调用后一个类的private成员,那么这个时候只需要把那些成员函数声明为后一个类的友元函数即可。就像下面这样:
这个set_chan属于Remote类,但是现在要把它声明为TV类的友元函数。
不过,这会引起一个问题。编译器必须要知道Remote是个类,而且这个set_chan是Remote类的一个成员函数,所以它必须要先看到Remote的声明式,这决定了Remote类的声明式必须出现在TV类的上面。
但是,因为这个set_chan是TV类的友元函数,那么Remote也必须先知道这个TV是个类才行。
那么为了满足这两者的要求,C++推出了类的前置声明式,如下图所示:
它的用法如下所示:
现在这个问题得以解决,所以由此可以得知,类的前置声明式的作用就是告诉下面某个标签是个类而已。
但是现在又出现了一个问题,那就是在Remote中有一个内联函数onoff,它调用了TV的对象进行代码的实现。因为onoff的代码写在Remote声明式中,编译器必须要在onoff调用TV对象的时候知道TV对象有onoff所要调用的东西。可实际上TV类的声明式在Remote类的下面,Remote类的上面只是个TV类的前置声明而已,Remote类的内部无法知道TV类具体长成什么样子,因此onoff要调用TV类对象的东西时表示茫然无知。
所以为了使TV对象的内部细节在onoff来看是赤裸裸的,就必须让TV类的声明式在onoff之上才行,也就是说让onoff的定义放在TV类的声明式之下。即下图所示:
在这里C++ Primer Plus的解决办法是在Remote类中只保留函数声明,把函数定义统统放在下面,如果是内联函数,你直接在函数定义上加上inline关键字即可。这是一种快刀斩乱麻的解决办法。
不同于其他成员函数,inline函数可以把定义放在头文件中,如下图所示:
测试代码及运行结果如下所示:
而其他函数就不能定义在头文件中了,如下图所示:
现在我把inline函数定义在cpp中。
从上图可知,inline函数只能定义在头文件中。
Inline函数具有内部连接属性,也就是说它只能存在于它被调用的地方,而且还必须是头文件,所以上面的onoff只能放在头文件中。
还需要注意的是,声明友元类时没必要使用类的前置声明式,虽然你可以选择这么做,那是因为友元类的声明式
足以说明它自己是个类。