从类类型到类类的隐式转换

Luc*_*uca 9 c++ type-conversion c++11

我正在研究用C++转换构造函数和转换运算符.到目前为止我学到的是,任何只带一个参数(以及任意数量的可选默认参数)的非显式构造函数表示对THAT类类型的隐式类类型转换,例如,如果类定义了一个构造函数,类型intI的一个参数可以int在需要该类类型的对象的任何地方使用:

(假设class_type有一个重载的+ =运算符)

class_type a;
a+=5;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,5被隐式转换(通过转换构造函数),class_type并调用重载的运算符.

现在,(至少对我来说)棘手的部分:我知道我可以将转换运算符定义为成员函数:

operator int() {....};
Run Code Online (Sandbox Code Playgroud)

将对象转换为class_type基本int类型,我可以使用如下转换:

class_type a;
a+5;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我已经读过通过其转换运算符将对象转换为int,然后调用内置和运算符.但是如果我定义了一个重载的+运算符来将两个class_type对象作为其参数呢?就像是

class_type operator+(const class_type&,const class_type &c);

编译器如何知道通过函数匹配调用哪一个?int仅当定义了内置运算符时,转换是否仅隐式发生?

谢谢!

编辑:

实际上,我已经尝试编写一些代码来有效地尝试它,结果发现我的编译器(g ++)不会发出任何模糊的调用错误!

这是类头(以及非memeber操作符+函数声明):

#include <iostream>

class wrapper {
    friend std::ostream &operator<<(std::ostream&,const wrapper&);
  public:
    wrapper()=default; 
    wrapper(int);
    int get();
    operator int() const;
    wrapper operator+(int);
  private:
    int a=10;
};

std::ostream &operator<<(std::ostream&,const wrapper&);
Run Code Online (Sandbox Code Playgroud)

这是主要代码:

#include "wrapper.h"

int main()
{
  using namespace std;
  wrapper w1;
  wrapper w2(5);
  cout<<w1<<" "<<w2<<endl;
  w1+1;  
}
Run Code Online (Sandbox Code Playgroud)

现在,我已经定义从一个转换构造int,以wrapper与从类型的转换运算符int(我也重载以打印一些结果<<输出操作符),但是当编译器计算表达式w1+1它似乎是细.怎么可能?

Vla*_*cow 15

例如,如果您有包含转换构造函数和转换运算符的以下类声明

struct A
{
    A( int x ) : x( x ) {}
    operator int() const { return x; }
    int x;
};        

const A operator +( const A &a1, const A &a2 )
{
    return A( a1.x + a2.x );
}
Run Code Online (Sandbox Code Playgroud)

声明

a1 + a2;
Run Code Online (Sandbox Code Playgroud)

其中a1和a2被声明为例如

A a1( 10 );
A a2( 20 );
Run Code Online (Sandbox Code Playgroud)

因为不需要调用转换函数,所以格式正确.两个操作数都匹配operator +的参数声明.

但是,如果你要写的话

a1 + 20;
Run Code Online (Sandbox Code Playgroud)

当编译器发出错误时,因为存在歧义.编译器可以应用转换构造函数A( int ) 将第二个操作数转换为类型,A并调用为类型对象定义的运算符A.或者它可以应用转换运算符operator int将第一个操作数转换为类型int并调用operator +类型对象的内置函数int.

为避免这种歧义,您可以使用函数说明符声明构造函数或运算符(或两者)explicit.

例如

    explicit A( int x ) : x( x ) {}
Run Code Online (Sandbox Code Playgroud)

要么

    explicit operator int() const { return x; }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,只存在一个隐式转换,并且没有任何矛盾.

我想附加上面的描述,即使用函数说明符声明它们,有时也可以隐式调用某些转换运算符explicit.

例如根据C++标准(6.4选择语句)

  1. ...作为表达式的条件的值是表达式的值,对于除switch之外的语句,上下文转换为bool;

和(5.16条件运算符)

1条件表达式从右到左分组.第一个表达式在上下文中转换为bool(第4条).

因此,例如,如果上面的类具有使用函数说明符声明的以下转换运算符 explicit

explicit operator bool() const { return x != 0; }
Run Code Online (Sandbox Code Playgroud)

然而,它将被隐含地称为例如以下声明中

A a( 10 );

std::cout << ( a ? "true" : "false" ) << std::endl;
Run Code Online (Sandbox Code Playgroud)

这里a将在条件运算符中转换为bool类型的对象.

编辑:你更新了这个表达式后的问题

w1+1; 
Run Code Online (Sandbox Code Playgroud)

与操作员完全匹配

wrapper operator+(int);
Run Code Online (Sandbox Code Playgroud)

无需转换.所以代码编译成功.