运算符重载(友元和成员函数)

发布于 2024-08-31 00:57:38 字数 109 浏览 2 评论 0原文

使用 friend 关键字进行运算符重载与作为类内的成员函数进行运算符重载有什么区别?

另外,在任何一元运算符重载的情况下(即作为友元与作为成员函数)有什么区别?

What is the difference between operator overloading using the friend keyword and as a member function inside a class?

Also, what is the difference in the case of any unary operator overloading (i.e. as a friend vs. as a member function)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

好听的两个字的网名 2024-09-07 00:57:39

成员函数要求左侧运算符必须是该类型。友元函数可以允许对左侧运算符进行隐式转换。

A member function requires that the left hand operator must be of that type. A friend function can allow implicit casting on the left hand operator.

故人的歌 2024-09-07 00:57:39

可以对右值调用成员函数,而不能用右值调用接受非常量引用的自由函数。例如,仅当您将 operator++ 实现为成员时,++function_returning_iterator_by_value() 才会编译。

Member functions can be called on rvalues, whereas free functions accepting references to non-const cannot be called with rvalues. For example, ++function_returning_iterator_by_value() only compiles if you implement operator++ as a member.

ゞ记忆︶ㄣ 2024-09-07 00:57:38

Jacob 是正确的……在类中声明的 friend 函数可以访问该类,但它根本不在类内部,而其他人都可以访问它。

对于不是类成员的运算符重载(也称为自由函数,它可能是友元,也可能不是),参数与操作数相同。对于类的成员,第一个操作数是“隐式参数”,它变为 this

隐式参数与自由函数的第一个参数在几个方面有所不同:

  • 它的类型是对类的引用,而自由函数可以为其第一个参数声明任何类型。
  • 它不参与隐式类型转换。 (它不会是由转换构造函数初始化的临时值。)
  • 它确实参与虚拟重写解析。 (虚拟重载将由第一个操作数的动态类型来选择,这对于没有额外代码的自由函数来说是不可能的。)

一元、二进制或 n 元的情况是相同的(对于operator())。

成员变异特权:更改第一个操作数的运算符(例如+==、前缀++)应该作为成员函数实现,并且应该专门实现所有重载的核心。 Postfix ++ 是二等公民;它的实现为 Obj ret = *this; ++ 这个;返回ret;。请注意,这有时会扩展到复制构造函数,其中可能包含 *this = 初始值设定项。

通勤者的自由规则:只有可交换运算符(例如/)才应该是自由函数;所有其他运算符(例如一元运算符)都应该是成员。交换运算符本质上会复制对象;它们被实现为 Obj ret = lhs; ret@=rhs; return ret; 其中 @ 是交换运算符,lhsrhs 是左侧和右侧参数,分别。

C++ 友谊的黄金法则:避免友谊。 friend 污染了设计的语义。 重载推论:如果遵循上述规则,重载很简单,那么 friend 是无害的。样板重载定义的交友允许将它们放置在 class { 大括号内。

请注意,某些运算符不能是自由函数:=->[](),因为该标准在第 13.5 节中有明确规定。我认为这就是全部......我认为一元 &* 也是如此,但我显然错了。不过,他们应该始终作为成员超载,而且只有在仔细考虑之后!

Jacob is correct… a friend function declared within a class has access to that class, but it's not inside the class at all, and everyone else has access to it.

For an operator overload which is not a member of the class (also called a free function, it may be a friend, or maybe not), the arguments are the same as the operands. For one which is a member of a class, the first operand is the "implicit argument" which becomes this.

The implicit argument is different from the first argument to a free function in a few ways:

  • Its type is reference-to-class, whereas the free function can declare any type for its first argument.
  • It does not participate in implicit type conversion. (It will not be a temporary initialized by a conversion constructor.)
  • It does participate in virtual override resolution. (A virtual overload will be chosen by the dynamic type of the first operand, which is not possible with free functions without extra code.)

The situation is the same for unary, binary, or n-ary (in the case of operator()).

Members privilege of mutation: Operators which change the first operand (eg +=, =, prefix ++) should be implemented as member functions, and should exclusively implement the guts of all overloads. Postfix ++ is a second-class citizen; it is implemented as Obj ret = *this; ++ this; return ret;. Note that this sometimes extends to copy-constructors, which may contain *this = initializer.

Rule of freedom for commuters: Only commutative operators (eg /) should be free functions; all other operators (eg unary anything) should be members. Commutative operators inherently make a copy of the object; they are implemented as Obj ret = lhs; ret @= rhs; return ret; where @ is the commutative operator and lhs and rhs are left-hand side and right-hand side arguments, respectively.

Golden rule of C++ friendship: Avoid friendship. friend pollutes the semantics of a design. Overloading corollary: Overloading is simple if you follow the above rules, then friend is harmless. friending boilerplate overload definitions allows them to be placed inside the class { braces.

Note that some operators cannot be free functions: =, ->, [], and (), because the standard specifically says so in section 13.5. I think that's all… I thought unary & and * were too, but I was apparently wrong. They should always be overloaded as members, though, and only after careful thought!

你没皮卡萌 2024-09-07 00:57:38

不同之处在于友元函数实际上位于全局范围内,因此您不需要成为该类的实例即可访问它。

The difference is that the friended function is actually in global scope, so you do not need to be an instance of the class to have access to it.

最佳男配角 2024-09-07 00:57:38

成员函数要求左侧运算符必须是该类型。
友元函数可以允许对左侧运算符进行隐式转换。

例如,假设我们创建一个 BigInt 类。我们创建一个成员函数operator + 来获取BigInt 的右手运算符。

现在我们还可以说 BigInt 有一个采用常规 int 的构造函数。该构造函数不是显式的(显式关键字),并且它采用一个参数。这意味着 C++ 可以隐式地从 int 转换为 BigInt。

当我们拥有这些东西时,我们可以这样做:

BigInt foo( 5 );
BigInt 条;
酒吧 = 富 + 5;

但我们不能这样做:

BigInt foo( 5 )
BigInt 条;
酒吧= 5 + 富;

但是,如果我们使用友元函数而不是成员函数,那么两者都可以工作。

A member function requires that the left hand operator must be of that type.
A friend function can allow implicit casting on the left hand operator.

So for example, lets say we create a BigInt class. And we create a member function operator + to take a right hand operator of BigInt.

Now lets also say BigInt has a constructor that takes a regular int. This constructor is NOT explicit (explicit keyword) and it takes one parameter. That means C++ can implitily convert from int to BigInt.

When we have these things we can do this:

BigInt foo( 5 );
BigInt bar;
bar = foo + 5;

But we CAN'T do this:

BigInt foo( 5 )
BigInt bar;
bar = 5 + foo;

However, if we used a friend function instead of a member function then both will work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文