2013-07-24 2 views
3

В следующем коде я пытаюсь получить функцию друга для доступа к частному члену класса. В моем понимании я правильно объявить его как функцию друга, но VS2012 дает мне ошибку:Функция друга не работает

error C2248: 'X::S::s_' : cannot access private member declared in class 'X::S' 

Может кто-нибудь предложить, что я делаю не так? Это самый простой пример, демонстрирующий ошибку компилятора, с которой я мог бы придумать.

namespace X 
{ 
    class S 
    { 
     friend std::string r(X::S &s); 
     std::unique_ptr<std::istream> s_; 
    }; 
} 
std::string r(X::S &s) 
{ 
    auto& x = s.s_; 
    return ""; 
} 

ответ

6

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

namespace X 
{ 
    class S 
    { 
     friend std::string r(S &s); 
     std::unique_ptr<std::istream> s_; 
    }; 

    std::string r(S &s) 
    { 
     auto& x = s.s_; 
     return ""; 
    } 
} 
+0

Как бы я объявить глобальную функцию друга вместо перемещения функции в пространство имен? Если я делаю friend std :: string :: r (S &s);, он говорит, что std :: string не имеет члена 'r'. – Graznarak

+0

@Graznarak, Помимо перемещения класса из пространства имен, я не уверен если вы можете. – chris

+4

@Graznarak: Попробуйте 'friend std :: string (:: r) (S & s);' Но вам понадобится форвардная декларация. –

5

Если вы хотите глобальный r:

namespace X 
{ 
    class S; 
} 

std::string r(X::S &s); 

namespace X 
{ 
    class S 
    { 
     friend std::string (::r)(X::S &s); 
     std::unique_ptr<std::istream> s_; 
    }; 
} 

std::string r(X::S &s) 
{ 
    auto& x = s.s_; 
    return ""; 
} 
+0

В моей системе достаточно дополнительных скобок вокруг ':: r'. Я не делал форвардной декларации класса X :: S'. – jxh

Смежные вопросы