簡體   English   中英

如何在C ++中強制不使用轉換構造函數

[英]How to force not to use conversion constructor in C++

我正在研究一個帶矩陣的項目,我遇到了重載運算符的問題。

我已經聲明了這些用戶友好的輸入/輸出功能:

friend std::istream& operator>>(std::istream& is, MathMatrix& m); //keyboard input
friend std::ostream& operator<<(std::ostream& os, const MathMatrix& m); // screen output
friend std::ifstream& operator>>(std::ifstream& ifs, MathMatrix& m); // file input
friend std::ofstream& operator<<(std::ofstream& ofs, const MathMatrix& m); // file output

在定義它們中的最后一個時,在這段簡單的代碼中,我遇到了一個錯誤,無法編譯:

// file output
std::ofstream& operator<<(std::ofstream& ofs, const MathMatrix& m) {
    //put matrix dimension in first line
    ofs << m.n << std::endl;
    //put data in third line
    for (int i=0; i<m.n; i++) {
        for (int j=0; j<m.n; j++) ofs << m(i,j) << " ";
        ofs << std::endl;
    }
    return ofs;
}

錯誤在ofs << mn (和ofs << m(i,j)的類似)。 它說:

const MathMatrix &m
Error: more than one operator "<<" matches these operands:
    function "operator<<(std::ofstream &ofs, const MathMatrix &m)"
    function "std::basic_ostream<_Elem, _Traits>::operator<<(int _Val) [with _Elem=char, _Traits=std::char_traits<char>]"
    operand types are std::ofstream << const int

過了一會兒我覺得問題可能就是我有一個像MathMatrix (int n)這樣的MathMatrix構造函數,因此編譯器可能會嘗試從int n轉換為MathMatrix(int n) 我不明白為什么它會這樣做,但這是我能想到的唯一解釋,給出IDE給出的解釋。

你能看到我錯過的東西嗎? 你知道怎么解決嗎?

如果在您的類中有一個構造函數,其單個參數的類型與您的類不同,則可以將其用於隱式類型轉換。 為了防止您只需要將該構造函數標記為顯式:

class MathMatrix {
public:
   explicit MathMatrix( int m );
...
};

始終將單個參數構造函數標記為顯式是個好主意(除非參數是相同的類類型,或者您確實需要這樣的類型轉換)

重載決策中存在一個微妙之處,導致在調用ofs << mn的函數時選擇函數之間存在模糊性。 這是一個重現問題的簡短示例:

struct Base
{
    void operator<<(int);
};

struct Derived : Base
{
};

struct converter
{
    converter(int);
};

void operator<<(Derived&, converter const&);

int main()
{
    const int i = 42;
    Derived d;
    d << i;
}

為什么電話不明確?

首先,成員函數Base::operator<<獲取Base&類型的附加參數,僅用於重載解析[over.match.funcs] / 2

候選函數集可以包含要針對同一參數列表解析的成員函數和非成員函數。 因此,參數列表和參數列表在此異構集中是可比較的,成員函數被認為具有額外的參數,稱為隱式對象參數 ,其表示已調用成員函數的對象。

由於成員函數(甚至在Derived繼承)是Base的成員函數,因此參數類型是Base& ,而不是Derived ; 見/ 4。

因此我們比較

void operator<<(Base&, int);                  // #0
void operator<<(Derived&, converter const&);  // #1

調用d << i的參數是Derived (左值)和const int 因此:

  1. 過載#0
    1. 對於第一個參數,需要派生到基礎的轉換
    2. 對於第二個參數,需要進行限定轉換( const int to int
  2. 過載#1
    1. 對於第一個參數,完全匹配(無轉換)
    2. 對於第二個參數,需要進行限定轉換,然后進行用戶定義的轉換( const int to intint to converter

轉換1.1比轉換2.1差,但轉換1.2優於轉換2.2。 因此,呼叫是模糊的。


如何解決歧義?

或者:

  • (首選)使MathMatrix的轉換顯式化
  • 只聲明一個operator<<(std::ostream&, MathMatrix const&) ,但沒有std::ofstream (這將使1.1等於1.2,因此重載#1成為更好的匹配)
  • 將調用中的std::ofstream顯式轉換為基類std::ostream (有助於以前的版本)
  • 隱藏有問題的重載,例如通過using std::operator<<;using聲明 using std::operator<<;

暫無
暫無

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

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