类类型之间的隐式转换

路卡

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

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

class_type a;
a+=5;

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

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

operator int() {....};

将对象转换为class_type原始int类型,我可以像这样使用该转换:

class_type a;
a+5;

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

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

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

谢谢!

编辑:

实际上,我试图编写一些代码来有效地进行尝试,结果证明我的编译器(g ++)不会发出任何歧义的调用错误!

这是类标头(以及非成员operator +函数声明):

#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&);

这是主要代码:

#include "wrapper.h"

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

现在,我已经定义了一个从转换intwrapperAND的转换构造函数,从类类型为转换了一个运算符int(为了显示一些结果,我也重载了<<输出运算符),但是当编译器对表达式求值时w1+1,似乎很好。怎么可能呢?

来自莫斯科的弗拉德

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

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 );
}

然后声明

a1 + a2;

例如,声明a1和a2的位置

A a1( 10 );
A a2( 20 );

格式正确,因为不需要调用转换函数。这两个操作数都与运算符+的参数声明匹配。

但是,如果您要写例如

a1 + 20;

当编译器由于存在歧义而发出错误时。编译器可以应用转换构造函数A( int )将第二个操作数转换为type,A然后调用为type对象定义的运算符A也可以应用转换运算符operator int将第一个操作数转换为type,intoperator +为type对象调用内置函数int

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

例如

    explicit A( int x ) : x( x ) {}

要么

    explicit operator int() const { return x; }

在这种情况下,将只存在一个隐式转换,并且没有歧义。

我想补充一下上面的描述,即使某些converion运算符可以用函数说明符声明,有时也可以隐式调用explicit

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

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

和(5.16条件运算符)

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

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

explicit operator bool() const { return x != 0; }

但是,例如在以下语句中将隐式调用它

A a( 10 );

std::cout << ( a ? "true" : "false" ) << std::endl;

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

编辑:更新您的问题后此表达式

w1+1; 

是运算符的完全匹配

wrapper operator+(int);

都不需要转换。因此,代码可以成功编译。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章