簡體   English   中英

為什么編譯器沒有檢測到錯誤的正確函數簽名?

[英]Why the Compiler does not detect correct function signature in error?

問題是參考這個 ,這是在不久前發布的。
盡管OP很樂意接受解決了他的問題的答案,但我對於為什么編譯器給出了看似錯誤的錯誤的細節感到有點興趣。

下面是我創建的一個小代碼示例,用於演示相同的代碼:

    class YourClass
    {
    };

    class YourClass2
    {
    };
    class MyClass
    {
        public:
            void doSomething(YourClass2 obj)
            {
                //Nothing more Interesting to do
            }

    };

    int main()
    {
        YourClass *ptr = new YourClass();
        MyClass obj;
        obj.doSomething(ptr);

        return 0;
    }

編譯海灣合作委員會(4.3.4)給出了一個看似奇怪的錯誤的結果:

prog.cpp: In function ‘int main()’:
prog.cpp:23: error: no matching function for call to ‘MyClass::doSomething(YourClass*&)’
prog.cpp:13: note: candidates are: void MyClass::doSomething(YourClass2)

所以問題是:
為什么編譯器會處理呼叫,

obj.doSomething(ptr);

作為對原型的函數的調用,

MyClass::doSomething(YourClass*&)

並不是

MyClass::doSomething(YourClass*)

這似乎是一個明顯的例子。

首先,請注意表達式 ptr (不是變量 ptr )的類型為YourClass *& 這個很重要; 它是引用類型可以工作的唯一方式(否則,當你執行YourClass *&x = ptr時,你將引用一個副本 ,這也是你的類YourClass *&x = (ptr + 1)失敗的原因)。 因此,編譯器開始使用MyClass::doSomething(YourClass *&)搜索函數。

當然,這個調用可以匹配原型MyClass::doSomething(YourClass *) 它也可以匹配MyClass::doSomething(const YourClass *)或許多其他。 可能存在數十個(或者,具有多個參數,容易數百或數千個)可能與此調用匹配的原型; 然而,沒有人能找到。

所以編譯器放棄了,並給出了錯誤。 在錯誤中,而不是列出每個理論上可能的匹配,它引用了一個最接近它最初尋找的原型; 也就是說, MyClass::doSomething(YourClass *&)

正如其他人所說,編譯器試圖提供幫助,可能會使您感到困惑。 讓我們從最簡單的錯誤開始:

錯誤:沒有用於調用obj.doSomething(ptr)匹配函數

雖然錯誤消息是正確的,但它提供的信息非常有限。 在這個例子中,代碼很容易遵循,但考慮更復雜的代碼。 你閱讀了錯誤信息,你可能會想...... 什么是obj?,什么是ptr? 所以它試圖幫助你並告訴你obj是什么:

錯誤:沒有匹配函數來調用'MyClass :: doSomething(ptr)'

好吧,那更好,它告訴你至少在你需要查找重載的類中,但考慮到類是std::ostream和函數operator<< ...有太多的重載,仍然,什么是ptr的類型? 所以它向前移動並試圖描述參數:參數是一個類型YourClass*左值 ...我已經看到過去產生的那種錯誤信息:

錯誤:沒有匹配函數來調用'MyClass :: doSomething',它將YourClass*左值作為參數。

好的,所以錯誤報告已經完成。 現在認為該函數可能有更多的參數,並且錯誤消息可以變成一個復雜的野獸(想象一下5的類型XXX的左值列表和一個類型為YYY的左值和......“)。 接下來的事情是使錯誤消息的語法同樣精確(參數的左值 - 重要性,或者右值 - 度將是重要的,因此必須存在一條信息)。 所以它再次重寫錯誤消息:

錯誤:沒有用於調用'MyClass :: doSomething(YourClass *&)'的匹配函數

問題是你試圖將其解釋為函數簽名,但它更像是函數調用的描述。

錯誤消息未在標准中定義,並且它們在一個編譯器之間不同,甚至在同一編譯器中從一個版本到另一個版本。 在一天結束時,您需要學習閱讀錯誤消息及其含義。

編譯器正試圖提供幫助。

MyClass::doSomething(YourClass*&)

這沒有命名任何函數:代碼中沒有與此匹配的函數。

YourClass*&是您嘗試傳遞給名為MyClass::doSomething的函數的參數的類型:參數( ptr )是左值,由&表示在錯誤中。

編譯器需要某種方法來區分左值參數和右值參數,以便為您提供盡可能多的有用診斷信息; 這是一種簡潔的方法。

編譯器不需要生成對您有意義的消息。 它需要告訴您代碼中存在錯誤。 現在它打印的消息是由編譯器決定的。 標准沒有說明它應該打印什么消息,什么不打印。 當編譯器打印錯誤消息時,在我看來,該錯誤消息可能是好的/有用的,或者是壞的/無用的,但不是“錯誤的”。

暫無
暫無

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

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