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

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

В другом классе, "Card", у меня есть переменная-член "my_Suit" и функция-член "нанизывать". Эта функция вызывает функцию «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);
}

Ответы [ 2 ]

1 голос
/ 25 января 2020

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

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

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

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

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

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

Исправлено Card::to_string():

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

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

#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

Live Demo on coliru

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

1 голос
/ 25 января 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) );
    }
...