运算符重载C ++中的friend与成员函数

时间:2017-03-29 09:15:44

标签: c++ operator-overloading friend-function

以前我学会了在C ++中重载操作符作为成员函数以及类的友元函数。虽然,我知道如何使用这两种技术在C ++中重载运算符。但我仍然感到困惑,**哪一个更好**?成员函数或朋友函数重载运算符,我应该使用哪个,为什么?  请指导我!您的回复将受到极大的赞赏。我很高兴并感谢你的回答。

4 个答案:

答案 0 :(得分:4)

选择不是“会员或朋友”,而是“会员或非会员” (友谊经常被过度使用,而且通常在学校教得太早。)

这是因为您始终可以添加免费功能可以调用的公共成员函数。

例如:

class A
{
public:
    explicit A(int y) : x(y) {}
    A plus(const A& y) const { return A{x + y.x}; }
private:
    int x;
};

A operator+(const A& lhs, const A& rhs) { return lhs.plus(rhs); }

至于如何选择:如果操作符没有将类的实例作为其左操作数,则必须是一个自由函数,否则它几乎是个人的问题品味(或编码标准,如果你不是一个人)。

示例:

// Can't be a member because the int is on the left.
A operator+ (int x, const A& a) { return A{x} + a; }

对于具有相应变异运算符的运算符(如++=),将变异运算符作为成员而另一个作为非成员运行是很常见的:

class B
{
public:
    explicit B(int y) : x(y) {}
    B& operator+= (const B& y) { x += y.x; return *this; }
private:
    int x;
};

B operator+(B lhs, const B& rhs) { return lhs += rhs; }

但你也可以拼写出来,当然:

class C
{
public:
    explicit C(int y) : x(y) {}
    C& add(const C& y) { x += y.x; return *this; }
private:
    int x;
};

C& operator+=(C& lhs, const C& rhs) { return lhs.add(rhs); }
C operator+(C lhs, const C& rhs) { return lhs += rhs; }

答案 1 :(得分:2)

会员功能和朋友不是两个相反的,其中您只需要选择一个。它们都可以被使用,例如,通过实现一个并让另一个调用它来避免重复代码。

struct A
{
    A operator+=(A const & second); 
};

A operator+(A const &first, A const &second)
{
    A temp(first);
    temp += second;
    return temp;
}

但是如果你想要选择一个函数,如果它需要成为成员,那么我遵循以下规则:实现一个非成员函数({{1}或者没有)当我有一个二元运算符来尊重我们期望的对称性。示例:使用friend并且可以隐式地将A转换为int(构造函数采用A),如果我有成员函数,那么将会是什么结果。

int

使用自由功能,结果就是。

A a1, a2; 
a1 + a2; // OK 
a1 + 42; // OK
42 + a2; // KO

使用这种可能性的具体C ++类是A a1, a2; a1 + a2; // Ok a1 + 42; // Ok 42 + a2; // Ok

std::string

总而言之,这里有一个good link来帮助你。

答案 2 :(得分:1)

可能没有固定的规则,所以我只是给出了我的观点:在可能时使用成员函数进行运算符重载。这样做的主要原因是我将运算符视为类的组成部分,并且类的逻辑更加本地化。

为操作符重载而选择自由函数的原因是为了使类尽可能精简(仅在需要时使用朋友)。

在某些情况下,运营商不能成为会员,因此在这种情况下不会进行讨论。主要成员函数将类实例作为第一个参数,并不总是可行的(例如,运算符<<对于i / o)。

答案 3 :(得分:1)

距离品味不远,但有些用例显然需要两种方式中的一种。

当运算符仅将您正在设计的类的成员作为参数时,封装投票使用成员函数。示例:添加两个对象:

class A {
    ...
    A operator + (const class A& other);   // naturally a member function
    ...
};

相反,当你正在编写的类的成员是操作符的第二个参数时,你只能使用友元函数

std::outstream& operator << (std::outstream& out, const class A& a);

class A {
    ...
    friend std::outstream& operator << (std::outstream& out, const class A& a); // must be friend here
};

最多可能是std::outstream的成员,但在标准C ++库中创建A类时,std::outstream类不存在...