首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >转换构造函数与转换运算符:优先级

转换构造函数与转换运算符:优先级
EN

Stack Overflow用户
提问于 2009-09-05 18:47:32
回答 2查看 15K关注 0票数 74

在这里读到一些关于转换运算符和构造器的问题,让我思考了它们之间的交互,也就是说,当有一个“模糊”调用时。考虑以下代码:

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++标准是appreciated)
  2. From一个面向对象的哲学观点,这是代码应该表现的方式吗?谁知道A对象应该如何成为B对象,是A还是B?根据C++的说法,答案是A --在面向对象的实践中,有没有什么东西表明应该是这样的呢?对我个人来说,无论哪种方式都是有意义的,所以我很想知道这个选择是如何做出的。

提前感谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-09-05 19:05:23

您确实复制了初始化,并且在转换序列中被认为执行转换的候选函数是转换函数和转换构造函数。这些都在你的箱子里

B(const A&)
operator B() 

现在,这就是你声明它们的方式。重载解析对此进行了抽象,并将每个候选对象转换为与调用的参数相对应的参数列表。这些参数包括

B(const A&)
B(A&)

第二个原因是转换函数是成员函数。A&是所谓的隐式对象参数,它是在候选函数是成员函数时生成的。现在,该参数的类型为A。绑定隐式对象参数时,非常数引用可以绑定到右值。因此,另一个规则是,当你有两个可行的函数,其参数是引用,那么拥有最少常量资格的候选人将获胜。这就是你的转换函数获胜的原因。尝试将operator B设置为常量成员函数。你会注意到模棱两可的。

从面向对象的哲学观点来看,这是代码应该表现的方式吗?谁知道更多关于A对象如何变成B对象的问题,A还是B?根据C++的说法,答案是A --在面向对象的实践中,有什么东西表明应该是这样的吗?对我个人来说,无论哪种方式都是有意义的,所以我很想知道这个选择是如何做出的。

根据记录,如果您将转换函数设置为常量成员函数,那么GCC将选择构造函数(所以GCC似乎认为B与它有更多的关系?)。切换到pedantic模式(-pedantic)以使其导致诊断。

标准文本,8.5/14

否则(即,对于剩余的复制-初始化情况),如13.3.1.4中所述枚举可以从源类型转换为目标类型或者(当使用转换函数时)转换为其派生类的用户定义的转换序列,并且通过重载解决(13.3)来选择最佳转换序列。

13.3.1.4

重载解析用于选择要调用的用户定义的转换。假设"cv1 T“是正在初始化的对象的类型,T是类类型,候选函数的选择如下:

  • T的转换构造函数(12.3.1)是候选的,初始化器表达式的类型是类类型"cv S",考虑了S及其基类的转换函数。那些不隐藏在S中并产生其cv非限定版本与T相同类型或是T的派生类的类型是候选函数。返回"reference to X“的转换函数返回类型为X的左值,因此被认为在选择候选函数的过程中生成X。

在这两种情况下,参数列表都有一个参数,即初始化器表达式。注意:此参数将与构造函数的第一个参数和转换函数的隐式对象参数进行比较。

13.3.3.2/3

  • 标准转换序列S1是比标准转换序列S2更好的转换序列,如果...S1和S2是引用绑定(8.5.3),引用引用的类型除了顶级的cv限定符之外都是相同的类型,并且S2初始化的引用引用的类型比S1初始化的引用引用的类型更符合cv限制。
票数 56
EN

Stack Overflow用户

发布于 2009-09-05 19:27:58

似乎MSVS2008对构造函数的选择有自己的看法:它在B中调用复制构造函数,而不考虑A的运算符的常量。因此,即使标准指定了正确的行为,也要小心。

我以为MSVS只是在转换运算符之前搜索合适的构造函数,但后来发现如果从B的构造函数中删除const word,它就会开始调用A的运算符B()。可能它对临时函数有一些特殊的行为,因为下面的代码仍然调用B的构造函数:

A a;

B b = a;
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1384007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档