使用普通函数重载运算符
在上一课中,我们将operator +重载为友元函数:
#include <iostream>
class Cents
{
private:
int m_cents;
public:
Cents(int cents) { m_cents = cents; }
// 用友元函数添加Cents + Cents
friend Cents operator+(const Cents &c1, const Cents &c2);
int getCents() const { return m_cents; }
};
// 注意:此功能不是会员功能!
Cents operator+(const Cents &c1, const Cents &c2)
{
// 用Cents构造函数和operator +(int,int)
// 因为这是一个友元函数,所以我们可以直接访问 m_cents
return Cents(c1.m_cents + c2.m_cents);
}
int main()
{
Cents cents1(6);
Cents cents2(8);
Cents centsSum = cents1 + cents2;
std::cout << "I have " << centsSum.getCents() << " cents." << std::endl;
return 0;
}
使用友元函数来重载操作符很方便,因为它使您可以直接访问正在操作的类的内部成员。在上面的初始Cents示例中,我们的友元函数版本的operator +直接访问了成员变量m_cents。
但是,如果您不需要该访问权限,则可以将重载运算符编写为普通函数。请注意,上面的Cents类包含一个访问函数(getCents()),它允许我们获取m_cents而无需直接访问私有成员。因此,我们可以将重载的operator +编写为非友元函数:
#include <iostream>
class Cents
{
private:
int m_cents;
public:
Cents(int cents) { m_cents = cents; }
int getCents() const { return m_cents; }
};
// 注意: 这个函数既不是成员函数也不是友元函数
Cents operator+(const Cents &c1, const Cents &c2)
{
// 用Cents构造函数和operator +(int,int)
// 这里我们不需要直接访问私有变量
return Cents(c1.getCents() + c2.getCents());
}
int main()
{
Cents cents1(6);
Cents cents2(8);
Cents centsSum = cents1 + cents2;
std::cout << "I have " << centsSum.getCents() << " cents." << std::endl;
return 0;
}
由于普通函数和友元函数几乎完全相同(它们只对私有成员具有不同级别的访问权限),因此我们通常不会区分它们。一个区别是类中的友元函数声明也可以作为原型。使用普通函数版本,您必须提供自己的函数原型。
Cents.h:
class Cents
{
private:
int m_cents;
public:
Cents(int cents) { m_cents = cents; }
int getCents() const { return m_cents; }
};
// 需要明确地为operator +提供原型,因此在其他文件中使用operator +知道存在这种重载 Cents运算符+(const Cents&c1,const Cents&c2);
Cents.cpp:
#include "Cents.h"
// 注意: 这个函数既不是成员函数也不是友元函数
Cents operator+(const Cents &c1, const Cents &c2)
{
// 用Cents构造函数和operator +(int,int)
// 这里我们不需要直接访问私有变量
return Cents(c1.getCents() + c2.getCents());
}
main.cpp中:
#include <iostream>
#include "Cents.h"
int main()
{
Cents cents1(6);
Cents cents2(8);
Cents centsSum = cents1 + cents2; // 如果在 Cents.h没有这个原型,将会编译失败
std::cout << "I have " << centsSum.getCents() << " cents." << std::endl;
return 0;
}
一般情况下,正常函数应优先于友元函数,如果可以使用现有的成员函数(触及类的内部函数越少越好)。但是,不要添加额外的访问函数只是为了将操作符重载为普通函数而不是友元函数!
规则:如果可以在不添加其他函数的情况下执行此操作,则首选将操作符重载为普通函数而不是友元函数。