Почему компилятор не обнаруживает правильную сигнатуру функции по ошибке? - PullRequest
7 голосов
/ 18 августа 2011

Вопрос касается этого , который был размещен немного раньше.
Хотя ОП был рад принять ответ, который решил его проблему, я был немного заинтригован деталями о том, почему компилятор выдал на первый взгляд ошибочную ошибку.

Ниже приведен небольшой пример кода, который я создал, чтобы продемонстрировать то же самое:

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

Компиляция this с GCC (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*)

, что кажется очевидным.

Ответы [ 4 ]

6 голосов
/ 18 августа 2011

Во-первых, обратите внимание, что выражение ptr (не переменная ptr) имеет тип YourClass *&. Это важно; это единственный способ, которым могут работать ссылочные типы (в противном случае вы бы делали ссылку на копию , когда вы делаете YourClass *&x = ptr, и это также, почему YourClass *&x = (ptr + 1) терпит неудачу). Таким образом, компилятор начинает поиск функции с MyClass::doSomething(YourClass *&).

Конечно, этот вызов может соответствовать прототипу MyClass::doSomething(YourClass *). Он также может соответствовать MyClass::doSomething(const YourClass *) или многим другим. Есть потенциально десятки (или, с несколькими параметрами, легко сотни или тысячи) прототипов, которые потенциально могут соответствовать этому вызову; однако ни один не мог быть найден.

Итак, компилятор сдается и выдает ошибку. В ошибке, скорее, перечисляя каждое теоретически возможное совпадение, он ссылается на один прототип, который наиболее точно соответствует тому, что он первоначально искал; MyClass::doSomething(YourClass *&).

4 голосов
/ 18 августа 2011

Как уже говорили другие, компилятор пытается быть полезным и, вероятно, вводит вас в заблуждение. Начнем с самой простой ошибки:

ошибка: нет соответствующей функции для вызова obj.doSomething(ptr)

Хотя сообщение об ошибке верно, информация, которую оно предоставляет, очень ограничена. В этом примере код прост для подражания, но рассмотрим более сложный фрагмент кода. Вы читаете сообщение об ошибке, и вы можете подумать ... что такое obj ?, что такое ptr? Поэтому оно пытается вам помочь и говорит вам, что такое obj:

ошибка: не найдена подходящая функция для вызова MyClass :: doSomething (ptr) '

Ну, это лучше, это говорит вам, по крайней мере, в каком классе вам нужно искать перегрузку, но учтите, что класс был std::ostream, а функция operator<< ... слишком много перегрузок, и все же, какой тип ptr? Таким образом, он движется вперед и пытается описать аргумент: Аргумент является lvalue типа YourClass* ... и я видел такой тип сообщения об ошибке, созданного в прошлом:

ошибка: не найдена соответствующая функция для вызова MyClass :: doSomething, который принимает в качестве аргумента значение YourClass*.

Хорошо, значит, отчет об ошибке завершен. Теперь подумайте, что функция может иметь больше аргументов, и сообщение об ошибке может превратиться в сложного зверя (представьте список из 5 "r-значения типа XXX и l-значения типа YYY и ..."). Следующее - сделать синтаксис сообщения об ошибке таким же точным (важен аргумент lvalue аргумента, или важен rvalue , так что часть информация должна присутствовать). Поэтому он снова переписывает сообщение об ошибке:

ошибка: нет соответствующей функции для вызова call MyClass :: doSomething (YourClass * &) ’

Проблема в том, что вы пытаетесь интерпретировать это как сигнатуру функции, но это скорее описание вызова функции.

Сообщения об ошибках не определены в стандарте, и они отличаются от одного компилятора к другому, даже от одной версии к другой в пределах одного и того же компилятора. В конце дня вам нужно научиться читать сообщения об ошибках и их значение.

1 голос
/ 18 августа 2011

Компилятор пытается помочь.

MyClass::doSomething(YourClass*&)

Это не называет никакой функции: в вашем коде нет функции, которая бы соответствовала этому.

YourClass*& - это тип аргумента, который вы пытаетесь передать функции с именем MyClass::doSomething: аргумент (ptr) является lvalue, представленным в ошибке как &.

Компилятору нужен какой-то способ отличить аргументы lvalue от аргументов rvalue, чтобы предоставить вам как можно больше полезной диагностической информации;это один краткий способ сделать это.

0 голосов
/ 18 августа 2011

Компилятору не требуется генерировать сообщения, которые должны иметь смысл для вас. Все, что нужно, это сказать вам, что в вашем коде есть ошибка. Теперь, какие сообщения он печатает, зависит от компилятора. Стандарт не говорит, какое сообщение он должен печатать, а что нет. Когда компилятор печатает сообщение об ошибке, это сообщение об ошибке может быть либо хорошим / полезным, либо плохим / бесполезным, но, на мой взгляд, не "неправильным".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...