当我查阅有关运算符重载的书籍和堆栈溢出文章时,我发现以下内容:
当重载运算符是成员函数时, this 绑定到左侧操作数。成员运算符函数的参数比操作数的数量少一个(显式)。
(Addison Wesley,C++ 入门)
所以我的问题是,由于*
(dereference) 运算符没有任何左操作数,它如何获取其参数(即对象本身或this
)?
当我查阅有关运算符重载的书籍和堆栈溢出文章时,我发现以下内容:
当重载运算符是成员函数时, this 绑定到左侧操作数。成员运算符函数的参数比操作数的数量少一个(显式)。
(Addison Wesley,C++ 入门)
所以我的问题是,由于*
(dereference) 运算符没有任何左操作数,它如何获取其参数(即对象本身或this
)?
对于所有前缀一元运算符,它对它后面的操作数进行操作。
作为一个附加问题,如果将重载的 * 运算符定义为非成员函数与成员函数,那么它的使用方式会有什么不同吗?
在大多数情况下,不,除了非成员函数不能访问该类的私有成员并且如果成员函数和非成员函数都存在,编译器需要使用重载决议来选择更高级别的函数,如果有' 没有更好的功能,它是模棱两可的调用,请参阅ADL
对于可靠的来源,您可以查看运算符重载,或者更好的是标准 C++ 中的第 13.5.1 [over.unary] 节:
前缀一元运算符应由不带参数的非静态成员函数(9.3)或带一个参数的非成员函数实现。因此,对于任何前缀一元运算符@,@x 可以解释为 x.operator@() 或 operator@(x)。如果运算符函数的两种形式都已声明,则 13.3.1.2 中的规则确定使用哪种解释(如果有)。有关后缀一元运算符 ++ 和 -- 的解释,请参见 13.5.7。2 同一运算符的一元和二元形式被认为具有相同的名称。[ 注意:因此,一元运算符可以在封闭范围内隐藏二元运算符,反之亦然。——尾注]
如果同时有成员和非成员的选择,请参见 13.3.1.2 [over.match.oper]
前缀对其后面*
的操作数进行操作。
对于定义operator*
为成员函数的用户,它是由 - 表达式引用的对象this
。
#include <iostream>
using namespace std;
struct S
{
auto operator*() const -> char const* { return "Hi there!"; }
};
auto main()
-> int
{ cout << *S() << endl; }
结果:
你好呀!
解引用运算符的工作方式与重载运算符的工作方式与普通运算符的工作方式完全相同。
int foo(int *p)
{
return *p;
}
在语句return *p;
中,取消引用运算符适用于指针p
。它在右侧传递给它:
作为重载运算符,它的工作方式相同。
class bar {
int *some_internal_ptr;
public:
int operator*() const {
return *some_internal_ptr;
}
// Other class members and methods...
};
int foo(bar p)
{
return *p;
}
当运算符的右侧*
是具有 operator*` 成员的类时,它作为类的重载方法被调用,与任何其他成员没有什么不同,以解决取消引用。
这是因为用法相同,这就是为什么许多 C++ 库算法与指针或 C++ 库运算符同样适用的原因。例如,std::copy()
可以按如下方式实现(我正在删减一些不相关的不相关的复杂性,这里不相关):
template<typename iter_type>
iter_type copy(iter_type b, iter_type e, iter_type t)
{
while (b != e)
{
*t=*b;
++t;
++b;
}
return t;
}
您可以将本机指针传递给std::copy
,或者传递带有重载*
运算符的类,例如迭代器,并且由于重载*
运算符与普通*
运算符的语法相同,因此相同的算法也适用于重载运算符。