- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
namespace A{
struct A{
inline void operator+(const int B) {}; // 1)
};
inline void operator+(const A& a,const int B) {}; // 2)
}
inline void operator+(const A::A& a,const int B) {}; // 3)
int main()
{
A::A a;
a+1; // compile questions
return 1;
}
上面的代码可以正常编译。
但如果 1) 被注释,则由于 2) 和 3) 处的“'a + 1' 中的 'operator+' 的模糊重载”而无法编译。我能理解operator+首先在类里面搜索,如果1)没有注释,编译没有问题是有原因的。我说的不对吗?
主要问题:如果 1) 被注释,为什么编译器找到了一个匹配的 operator+,它继续寻找其他的?我也很好奇应该先找到哪个。 (根据How does the operator overload resolution work within namespaces?的信息,我认为应该立即停止)
第二个问题:
namespace A{
struct A{
inline void operator+(const long int B) {}; // 4), the input parameter type has been changed to long int
};
inline void operator+(const A& a,const int B) {}; // 5)
void test();
}
inline void operator+(const A::A& a,const int B) {}; // 6)
void A::test()
{
A a; // a)
a+ 1;
}
int main()
{
A::A a;
a+1; // b)
return 1;
}
由于 4) 和 5).,a) 处的编译不明确错误。
由于 4)、5) 和 6).,b) 处的编译错误
问题 i)
对于a)和b),为什么编译器已经在4)处找到了operator+ with (const long int input parameter type ),它是struct A中的成员运算符函数,它仍然继续寻找其他的。在我看来,编译器应该停在那里给出类型错误信息。应该和memeber函数的入参类型完全匹配的情况一样,停止寻找其他的。
问题2)
我认为编译器应该在 4) 处停止并给出类型错误信息。如果继续,为什么成员函数重载函数(long int)与输入参数完全匹配的非成员具有相同的分辨率排名?在这种情况下,我认为如果编译器决定继续搜索,则输入参数完全匹配的非成员情况应该获胜,这更有意义。
最佳答案
它在 C++ 标准中解释,“13.3.1.2 表达式中的运算符”部分,第 2 点:
If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator.
根据进一步的解释,a+1
将被转换为 a.operator+(1)
(成员函数)或 operator+(a,1)
(非成员函数)。
第 3 点解释说:
for a binary operator @ with a left operand of a type whose cv-unqualified version is T1 and a right operand of a type whose cv-unqualified version is T2, three sets of candidate functions, designated member candidates, nonmember candidates and built-in candidates, are constructed as follows:
- if T1 is a complete class type, the set of member candidates is the result of the qualified lookup of T1::operator@
这解释了为什么 (1) 在激活时被选中。当您将其注释掉时,候选成员集合为空。然后,根据标准中的下一个项目符号:
- The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls except that all member functions are ignored.
根据这些规则,由于您的表达式在 main()
中并且不包含在命名空间中,因此会找到两个候选函数,当然,这对编译器来说是不明确的。
您可以通过 main()
中的以下语句轻松区分使用哪个运算符:
using A::operator+;
如果你在命名空间 A 中的函数中使用表达式 a+1 也不会产生歧义:
//...your code preceding the main()
namespace A{ // reopen the namespace
void f()
{
A a;
a + 1; // version of the namespace is taken first
}
}
命名空间中定义的运算符将首先被采用(只要 (1) 仍然被注释掉)。
关于第二个问题
首先要注意的是:如果成员函数使用 int
作为参数,就像其他两个函数一样,就不会有歧义,并且会像您的第一个问题一样为两个表达式选择 (4) .如果所有三个函数都使用 long
而不是 int
作为参数,也会发生同样的情况。
您具有相同的名称但不同的参数这一事实要求我们在标准的第 13.3.1.2 节中更深入地挖掘名称隐藏和重载规则。第 6 点指出:
The set of candidate functions for overload resolution is the union of the member candidates, the non-member candidates, and the built-in candidates. The argument list contains all of the operands of the operator. The best function from the set of candidate functions is selected according to 13.3.2 and 13.3.3
13.3.2 是关于可行函数,即具有相同数量的参数以及参数类型和参数类型之间的隐式转换。
13.3.3 是关于选择最佳可行函数。 “如果恰好有一个可行函数比所有其他可行函数更好,那么它就是一个由重载决议选择;否则调用格式错误”。
在 (a) 的情况下,有两个最佳可行函数:具有转换的成员函数 (4) 或没有转换的非成员函数,在命名空间 (5) 内(因为 test() 在命名空间中) .因此模棱两可。
在 b) 的情况下,存在三个最佳可行函数:与 (a) 和 (6) 中的相同。但请注意,如果 (6) 将使用 long,则不会导致歧义,因为成员函数会获胜。
关于c++ - 运算符重载解析在 namespace 内工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26517376/
假设我有一个类,我在其中重载了运算符 == : Class A { ... public: bool operator== (const A &rhs) const; ... };
我知道你不应该使用 std::find(some_map.begin(), some_map.end()) 或 std::lower_bound,因为它会采用线性时间而不是 some_map.lowe
我正在尝试在 Haskell 中定义 Vector3 数据类型,并允许在其上使用 (+) 运算符。我尝试了以下方法: data Vector3 = Vector3 Double Double Doub
我已经为我的类图将运算符重载为“-”。它的用途并不完全直观(糟糕的编码 - 我知道)但是如果我做 graph3 = graph2-graph1 那么图 3 是应该只接收图 2 和图 1 中的那些顶点。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Operator overloading 我想重载 以按字母顺序排列字符串,但我不确定该怎么做。 如何再次
下面的代码给我一个编译错误。谁能告诉我为什么? class mytype { public: int value; mytype(int a) { value = a;
这有什么问题吗? class Vec2 attr_accessor :x, :y # ... def += (v) @x += v.x @y += v.y retu
是否可以重载 [] 运算符两次?允许这样的事情:function[3][3](就像在二维数组中一样)。 如果可能的话,我想看看一些示例代码。 最佳答案 您可以重载 operator[] 以返回一个对象
我的团队目前正在与 Lua 合作,创建一个 android 游戏。我们遇到的一件事是表面上无法创建重载构造函数。 我习惯于使用默认值设置一个对象,然后在需要时使其过载。 前任: apples() {
我有一个网页,在某个时候显示一个导航栏,它只不过是一个 a 元素的列表 (ul)。所述 a 元素的大多数样式规则都是通用的。唯一应该改变的部分是要显示的图像,可以从列表中每个 li 元素的 id 标签
我对使用/重载“范围步长”运算符(.. ..)很感兴趣,但我终其一生都无法了解如何使用它。 在文档中它说 // Usage: start .. step .. finish 但是在 F# shell
Java 11(可能无关紧要): public static String toString(Object obj) { return ReflectionToStringBuilder.to
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我无法理解以下代码(针对行号进行注释) class Base { void m1(Object o) { } void m2(String o) { } } publi
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
class myclass{ //definitions here }; myclass e; int myarray[10]; /* Do something... */ e = myarray;
为什么不能将下标运算符(operator [])作为 friend 函数重载? 最佳答案 正如Bjarne Stroustrup在D&E book中所说: However, even in the o
我有以下代码片段: #include using namespace std; struct Integer{ int x; Integer(const int val) : x(v
因此,我有一个问题是我最近尝试重载 namespace Eng { /** * A structure to represent pixels */ typedef
如何重载onResume()以正确的方式工作?我想从 activity 返回到 MainActivity ,我希望在其中具有与应用程序启动后相同的状态。我想使用 recreate() 但它循环了或者类
我是一名优秀的程序员,十分优秀!