Определение функции в классе требует такой же функции в другом классе: ошибка компиляции

У меня есть класс перечисления Suit и я определил строку функции to_string(Suit e)

В другом классе, Card, у меня есть переменная-член my_Suit и функция-член to_string. Эта функция вызывает функцию to_string с параметром my_Suit.

При компиляции получаю ошибку, что компилятор (g++) ищет функцию Card::to_string(Suit&), но этой функции не существует (не в рамках указанной области, Card::).

Ошибка гласит:

ошибка: нет соответствующей функции для вызова ‘Card::to_string(Suit&)’

кандидат: std::__cxx11::string Card::to_string()

Как мне объяснить компилятору, что он должен искать функцию, определенную вне класса?

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

#include <iostream>

/********************  enum class Suit  ********************/

enum class Suit
{
    Clubs, Spades, Hearts, Diamonds
};

std::string to_string(Suit e) 
{
    return ("calling 'to_string' function with Suit as parameter");
}

/********************  clas Card  ********************/

class Card
{

    private:
        Suit m_Suit;
    public:
        Card()  { m_Suit = Suit::Clubs; }

        std::string to_string() 
        {
            return ( to_string(m_Suit) );
        }
};

int main()
{
    std::cout << "Hello world!\n";
    return (0);
}

person J. Adriaenssens    schedule 25.01.2020    source источник
comment
К вашему сведению: Область   -  person Scheff's Cat    schedule 25.01.2020


Ответы (2)


Как уже подозревал ОП, это проблема области.

class Card имеет собственную область действия и предоставляет элемент Card::to_string().

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

В этом случае разрешение имени не потерпело неудачу, а предоставило кандидата.

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

Следовательно, есть некоторая явная помощь, необходимая оператору области действия (::).

Фиксированный Card::to_string():

        std::string to_string() 
        {
            return ::to_string(m_Suit);
        }

Фиксированный образец ОП:

#include <iostream>

/********************  enum class Suit  ********************/

enum class Suit
{
    Clubs, Spades, Hearts, Diamonds
};

std::string to_string(Suit e) 
{
    return ("calling 'to_string' function with Suit as parameter");
}

/********************  class Card  ********************/

class Card
{

    private:
        Suit m_Suit;
    public:
        Card()  { m_Suit = Suit::Clubs; }

        std::string to_string() 
        {
            return ::to_string(m_Suit);
        }
};

int main()
{
    std::cout << Card().to_string() << '\n';
    return (0);
}

Выход:

calling 'to_string' function with Suit as parameter

Текущая демонстрация на coliru

Кстати. операторы области действия в целом разрешаются во время компиляции и не влияют на поведение во время выполнения.

person Scheff's Cat    schedule 25.01.2020

Имя функции to_string, объявленное в глобальном пространстве имен, скрыто объявлением того же имени в области видимости класса Card.

Поэтому используйте квалифицированное имя. Например

    std::string to_string() 
    {
        return ( ::to_string(m_Suit) );
    }

Или используйте объявление использования, например

    std::string to_string() 
    {
        using ::to_string;
        return ( to_string(m_Suit) );
    }
person Vlad from Moscow    schedule 25.01.2020