c++ - 从类类型到类类型的隐式转换

标签 c++ c++11 type-conversion

我正在研究 C++ 中的转换构造函数和转换运算符。 到目前为止我学到的是,任何只接受一个参数(和任意数量的可选默认参数)的非显式构造函数都表示到该类类型的隐式类类型转换,例如,如果一个类定义了一个具有一个 int 类型的参数 我可以在任何需要该类类型的对象的地方使用 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 运算符+(const class_type&,const class_type &c);

编译器如何通过函数匹配知道调用哪一个? 仅当仅定义内置运算符时才会隐式转换为 int 吗?

谢谢!

编辑:

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

这是类头(连同非成员运算符+函数声明):

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

现在,我已经定义了一个从 intwrapper 的转换构造函数和一个从类类型到 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 ) 将第二个操作数转换为 A 类型,并调用为 A 类型的对象定义的运算符.或者它可以应用转换运算符operator int将第一个操作数转换为类型int并为类型的对象调用内置的operator + int.

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

例如

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

    explicit operator int() const { return x; }

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

我想补充上面的描述,有时一些转换运算符可以被隐式调用,即使它们是用函数说明符 explicit 声明的。

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

  1. ...The value of a condition that is an expression is the value of the expression, contextually converted to bool for statements other than switch;

and (5.16 条件运算符)

1 Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 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);

都不需要转换。所以代码编译成功。

关于c++ - 从类类型到类类型的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32068106/

相关文章:

C++ 字符串 cout 字符丢失

c++ - 尝试删除列表中的指针会导致内存使用量不断增长

multithreading - 如何创建运行抽象类的成员函数的 std::thread?

c++ - PlatformToolset 和 "deleted function"错误 (C2280)

c - *((int *) arg) 是做什么的?

c++ - 检查输入有效性?

c++ - 模板和 std::pair 列表初始化

c++ - 是否可以将 vector<shared_ptr<T>> 传递给 const vector<shared_ptr<const T>>& 参数?

c++11 - 关于在 C++11 中初始化向量

c# - 为什么 Cast<double>() 不能对 IEnumerable<int> 起作用?