Перегрузка функций / методов C ++: путаница типов данных? - PullRequest
9 голосов
/ 28 октября 2009

У меня возникли проблемы с перегрузкой методов в C ++. В качестве примера проблемы у меня есть класс с несколькими перегруженными методами, и у каждого метода есть один параметр с различным типом данных. Мой вопрос: есть ли определенный порядок в классе, в котором должны появляться эти методы, чтобы убедиться, что правильный метод вызывается в зависимости от типа данных его параметров?

class SomeClass{
    public:
    ...
    void Method(bool paramater);
    void Method(std::string paramater);
    void Method(uint64_t paramater);
    void Method(int64_t paramater);
    void Method(uint8_t paramater);
    void Method(int8_t paramater);
    void Method(float paramater);
    void Method(double paramater);
    void Method(ClassXYZ paramater);
}

Я заметил, что возникла проблема, потому что при запуске:

Method("string");

это звонило:

Method(bool paramater);

Ответы [ 7 ]

23 голосов
/ 28 октября 2009

Порядок не имеет значения. Вызываемый метод выбирается путем анализа типов аргументов и сопоставления их с типами параметров. Если нет точного соответствия, выбирается метод наилучшего соответствия. В вашем случае это метод bool.

Вы предоставляете аргумент типа const char[7]. В соответствии с правилами перегрузки C ++, лучший способ здесь - разрешить распаду const char[7] до const char *, а затем преобразовать его в bool с помощью стандартного преобразования. Путь с преобразованием в std::string считается худшим, поскольку он будет включать пользовательское преобразование из const char * в std::string. Обычно пользовательские преобразования теряют процесс разрешения перегрузки по сравнению со стандартными преобразованиями. Это то, что происходит и в вашем случае.

Если вам нужна здесь версия std::string, предоставьте явную перегрузку для типа const char * и делегируйте вызов версии std::string, явно преобразовав аргумент в тип std::string

void Method(const char *paramater /* sic! */)
{
  Method(std::string(paramater));
}
5 голосов
/ 28 октября 2009

Строковый литерал "string" имеет тип const char[], который может быть безразлично преобразован в bool. Это лучший кандидат для преобразования в одну из ваших перегруженных функций, хотя вряд ли она будет самой полезной.

Если ваше намерение состояло в том, чтобы строковые литералы обрабатывались перегрузкой, принимающей std::string, то вам нужно добавить перегрузку, принимающую const char*, и заставить реализацию вызывать версию std::string.

4 голосов
/ 28 октября 2009

Заказ не имеет значения. Проблема в том, что когда вы вызываете

Method("string");

вы передаете const char []. Это будет преобразовано в bool неявно. Что вы хотите сделать, это передать std :: string в явном виде:

Method( std::string("string"));
2 голосов
/ 28 октября 2009

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

class SomeClass
{
    public:
    ...
    template <typename T>
    void Method(T paramater);
};
1 голос
/ 22 декабря 2009

Вы можете добавить ключевое слово explict , чтобы получить предполагаемый аргумент.

1 голос
/ 28 октября 2009

Помимо строкового вопроса, есть еще один. int64_t и int8_t - это (обычно) определения типа. Поскольку typedefs являются просто псевдонимами, они могут ссылаться на тот же тип, в этом случае перегрузка не будет работать. Но это вряд ли в вашем случае. Просто хотел упомянуть об этом.

1 голос
/ 28 октября 2009

Как уже говорил Чарльз, это происходит из-за нежелательного неявного преобразования. Если вы хотите избежать этого, используйте конструктор std :: string: Method(std::string("string")); или приведите его к std :: string:

Method(static_cast<std::string>("string"));

Однако порядок ваших объявлений не важен. Также проверьте правильность написания слова «параметр»;)

...