簡體   English   中英

從類類型到類類的隱式轉換

[英]implicit conversions from and to class types

我正在研究用C ++轉換構造函數和轉換運算符。 到目前為止我學到的是,任何只帶一個參數(以及任意數量的可選默認參數)的非顯式構造函數表示對THAT類類型的隱式類類型轉換,例如,如果類定義了一個構造函數, 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 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&);

這是主要代碼:

#include "wrapper.h"

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

現在,我已經定義了從intwrapper的轉換構造函數以及從類類型到int的轉換運算符(我還重載了<< output運算符以便打印一些結果),但是當編譯器計算表達式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 );

因為不需要調用轉換函數,所以格式正確。 兩個操作數都匹配operator +的參數聲明。

但是,如果你要寫的話

a1 + 20;

當編譯器發出錯誤時,因為存在歧義。 編譯器可以應用轉換構造函數A( int )將第二個操作數轉換為類型A並調用為類型A對象定義的運算符。 或者它可以應用轉換運算符operator int將第一個操作數轉換為int類型,並為int類型的對象調用內置operator +

為了避免這種歧義,您可以使用函數說明符explicit來聲明構造函數或運算符(或兩者)。

例如

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

要么

    explicit operator int() const { return x; }

在這種情況下,只存在一個隱式轉換,並且沒有任何矛盾。

我想附加上面的描述,有時一些轉換運算符可以隱式調用,即使它們是使用函數說明符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);

無需轉換。 所以代碼編譯成功。

您可以輕松地嘗試查看編譯器的功能:

#include <iostream>

struct ABC {
    int v;
    ABC(int x) : v(x) { }
    operator int() const { return v; }
    void operator +=(ABC const &that) {
        v += that.v;
    }
};

ABC operator+(ABC const &lhs, ABC const &rhs) {
    return { lhs.v + rhs.v };
}

int main() {
    ABC a(5);
    std::cout << a + 1 << '\n';
    a += 10;
    std::cout << a << '\n';
}

如果我定義了一個重載的+運算符來取兩個class_type對象作為它的參數怎么辦?

GCC

錯誤:'operator +'的模糊重載(操作數類型是'ABC'和'int')

編譯器看到兩個候選者: operator+(int, int) <built-in>ABC operator+(const ABC&, const ABC&) 這意味着它不僅可以隱式地將a + 55轉換為a而且將aint 發布這些轉換后, operator+函數都會成為潛在匹配。

編譯器如何知道通過函數匹配調用哪一個?

因此不知道錯誤。

轉換為int只會在只定義內置運算符時隱式發生嗎?

是的,否則它不會自動將class_type轉換為int 但是, intclass_type會隱式發生,除非你使class_type的構造函數explicit

explicit ABC(int x) : v(x) { }

如果您可以訪問C ++ 11,那么您還可以顯式轉換函數:

explicit operator int() const { return v; }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM