gpt4 book ai didi

c++ - 转换构造函数与转换运算符 : precedence

转载 作者:IT老高 更新时间:2023-10-28 12:12:48 33 4
gpt4 key购买 nike

在这里阅读一些关于转换运算符和构造函数的问题让我想到了它们之间的交互,即当存在“模糊”调用时。考虑以下代码:

class A;

class B {
public:
B(){}

B(const A&) //conversion constructor
{
cout << "called B's conversion constructor" << endl;
}
};

class A {
public:
operator B() //conversion operator
{
cout << "called A's conversion operator" << endl;
return B();
}
};

int main()
{
B b = A(); //what should be called here? apparently, A::operator B()
return 0;
}

上面的代码显示“调用A的转换运算符”,意思是调用转换运算符而不是构造函数。如果您从 A 中删除/注释掉 operator B() 代码,编译器将愉快地转而使用构造函数(无需对代码进行其他更改)。

我的问题是:

  1. 由于编译器不认为 B b = A(); 是一个模棱两可的调用,因此这里必须存在某种优先级。这个优先级究竟是在哪里建立的? (来自 C++ 标准的引用/引用将不胜感激)
  2. 从面向对象的哲学观点来看,这是代码应该表现的方式吗?谁更了解A 对象应该如何成为B 对象、AB?根据 C++,答案是 A——在面向对象的实践中是否有任何东西表明应该是这种情况?就我个人而言,无论哪种方式都有意义,所以我很想知道是如何做出选择的。

提前致谢

最佳答案

您进行复制初始化,并且考虑在转换序列中进行转换的候选函数是转换函数和转换构造函数。这些是你的情况

B(const A&)
operator B()

现在,这就是您声明它们的方式。重载解决方案从中抽象出来,并将每个候选者转换为与调用参数相对应的参数列表。参数是

B(const A&)
B(A&)

第二个是因为转换函数是成员函数。 A& 是所谓的隐式对象参数,当候选者是成员函数时生成。现在,参数的类型为 A。绑定(bind)隐式对象参数时,非常量引用可以绑定(bind)到右值。因此,另一条规则说,当您有两个参数为引用的可行函数时,具有 fewest const 资格的候选人将获胜。这就是您的转换功能获胜的原因。尝试使 operator B 成为 const 成员函数。你会注意到一个模棱两可的地方。

From an object-oriented philosophical standpoint, is this the way the code should behave? Who knows more about how an A object should become a B object, A or B? According to C++, the answer is A -- is there anything in object-oriented practice that suggests this should be the case? To me personally, it would make sense either way, so I'm interested to know how the choice was made.

郑重声明,如果你把转换函数设为const成员函数,那么GCC会选择构造函数(所以GCC似乎认为B与它有更多的业务往来?)。切换到迂腐模式(-pedantic)以使其引起诊断。


标准,8.5/14

Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3).

13.3.1.4

Overload resolution is used to select the user-defined conversion to be invoked. Assuming that "cv1 T" is the type of the object being initialized, with T a class type, the candidate functions are selected as follows:

  • The converting constructors (12.3.1) of T are candidate functions.
  • When the type of the initializer expression is a class type "cv S", the conversion functions of S and its base classes are considered. Those that are not hidden within S and yield a type whose cv-unqualified version is the same type as T or is a derived class thereof are candidate functions. Conversion functions that return "reference to X" return lvalues of type X and are therefore considered to yield X for this process of selecting candidate functions.

In both cases, the argument list has one argument, which is the initializer expression. [Note: this argument will be compared against the first parameter of the constructors and against the implicit object parameter of the conversion functions. ]

还有13.3.3.2/3

  • Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if [...] S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.

关于c++ - 转换构造函数与转换运算符 : precedence,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1384007/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com