有的时候,我们既可以用成员函数实现某个功能,也可以用非成员非友元函数实现:
class Test
{
public:
Test(string string1 = "hello ",string string2 = "world!"):s1(string1),s2(string2){}
void sayHello(){cout<<s1;}
void sayWorld(){cout<<s2<<endl;}
void sayHelloWorld(){sayHello();sayWorld();}
private:
string s1;
string s2;
};
void SayHelloWorld(Test t)
{
t.sayHello();
t.sayWorld();
}
int main()
{
Test a;
// a.sayHelloWorld();
SayHelloWorld(a);
return 0;
}
那么两种方法哪个比较好呢?答案是后者。
首先,我们明白封装的重要性。封装是得我们可以在接口不变的前提下,修改内部实现的细节,使得程序更有弹性。那么如何衡量封装的程度呢?越少的代码看到数据,封装的就越好。所以如果是非成员、非友元函数,那么它并没有增加访问private的成员的函数的数量。而如果定义为成员函数,这个函数是有能力访问private成员的。违背了“越少的代码看到数据,封装的就越好”的原则。
当然,这个函数是non-member、non-frined函数,是针对这个类而言的。这意味着这个函数可能是其他类的某个成员函数(java和c#程序员奔泪)。
一个好的管理类和non-member、non-frined函数的策略是:假设有多个non-member、non-frined函数函数,而且它们并没有什么关系的话,它们的声明应该是在不同的头文件中的。可以使用一个命名空间将它们包起来,这刚好利用了命名空间可以跨文件定义的优势。而且这样很方便函数的扩展:如果有新的函数,那么只要把它的声明也放在同一个命名空间中即可。
总之,与使用成员函数相比,使用non-member、non-frined函数会增强类的封装性。