Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > friend class


Автор: _GRIN_ 2.12.2011, 13:38
Преамбула - всегда объявлял друзей класса прям в тебе класса без всякого forward declartion:
Код

class MyClass
{
firiend class MyFriendClass;
... some data ...
};

В основном использовал "друзей" для юнит-тестов

Недавно коллега увидел это (мы с ним фэйл в юнит-тесте разбирали) и сказал, что так (без forward declaration) по стандарту работать не должно.
Я чутка погуглил, но ничего явно запрещающего или явно разрещающего использование "друзей" без форвард декларейшн  не нашёл.

Подскажите, где в стандарте искать данную инфу?
А то тут у нас холивар намечается =)

Автор: rumit7 2.12.2011, 14:06
Цитата(_GRIN_ @ 2.12.2011,  13:38)
Подскажите, где в стандарте искать данную инфу?
А то тут у нас холивар намечается =)

C++ STANDARD-2003, раздел 11.4.9:

"For a friend class declaration, if there is no prior declaration, the class that is specified belongs to the innermost enclosing non-class scope, but if it is subsequently referenced, its name is not found by name lookup until a matching declaration is provided in the innermost enclosing nonclass scope."

Автор: newbee 2.12.2011, 14:10
Странный у тебя холивор намечается... Друх сказал тебе что-то с отсылкой на стандарт, так пусть же приведет пруф и тыкнет пальцем прямо в стандарт.

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

Автор: rumit7 2.12.2011, 14:25
Цитата(rumit7 @ 2.12.2011,  14:06)
Цитата(_GRIN_ @ 2.12.2011,  13:38)
Подскажите, где в стандарте искать данную инфу?
А то тут у нас холивар намечается =)

C++ STANDARD-2003, раздел 11.4.9:

"For a friend class declaration, if there is no prior declaration, the class that is specified belongs to the innermost enclosing non-class scope, but if it is subsequently referenced, its name is not found by name lookup until a matching declaration is provided in the innermost enclosing nonclass scope."

Код

namespace N
{    
    class A
    {
        friend class B;
    private:    
        static int value;
    };
}

//namespace N
//
    class B
    {
    public:
        void f()
        {
            N::A::value = 10;    // compilation error: ‘int N::A::value’ is private
        }
    };
//}


Раскомментируйте и ошибка компиляции исчезнет.

Автор: newbee 2.12.2011, 14:28
Вот rumit7 умничка написал кодом про неймспейсы то, что я вылила в потоке сознания )))

Автор: rumit7 2.12.2011, 14:33
Цитата(newbee @ 2.12.2011,  14:28)
Вот rumit7 умничка написал кодом про неймспейсы то, что я вылила в потоке сознания )))

 smile 
..только вот у Вас как всегда лучше получилось..

Автор: baldina 2.12.2011, 17:37
решаемо
Код

class B;

namespace N
{    
    class A
    {
        friend class ::B;
    private:    
        static int value;
    };
}

class B
{
  public:
  void f() {
    N::A::value = 10;
  }
};


Автор: newbee 2.12.2011, 18:13
Цитата(baldina @  2.12.2011,  18:37 Найти цитируемый пост)
решаемо
Ты руками сделал форвард-декларацию, так нечестно, топик о другом.

Автор: baldina 3.12.2011, 22:17
форвард есть, сжульничал. хотел показать что к глобальному namspace доступ можно получить

Автор: _GRIN_ 8.12.2011, 03:51
baldina, gcc твой пример не компилит - гляди лог:

исходник:
Код

//tst_friend_namespace.cpp 
class B;

namespace N
{    
    class A
    {
        friend class ::B;
    private:    
        static int value;
    };
}

class B
{
  public:
  void f() {
    N::A::value = 10;
  }
};

int main(int,char**)
{
    B obj_b;
    obj_b.f();
    return 0;
}


попытка компиляции:
Код

grin@grinnote:~/1_work/research/tst_friend_namespace$ g++ tst_friend_namespace.cpp 
/tmp/ccMbarYk.o: In function `B::f()':
tst_friend_namespace.cpp:(.text._ZN1B1fEv[B::f()]+0x5): undefined reference to `N::A::value'
collect2: ld returned 1 exit status


Код

gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 


Но если работать не со статик-переменными, то всё работает =)
Код

#include <stdio.h>

class B;

namespace N
{    
    class A
    {
        friend class ::B;
    private:    
        int m_value;
    };
}

class B
{
public:
  void setValue(N::A*obj_a,int val)const
  {
    obj_a->m_value = val;
  }
  int value(const N::A*obj_a)const
  {
    return obj_a->m_value;
  }
};

int main(int,char**)
{
    N::A obj_a;
    B obj_b;
    obj_b.setValue(&obj_a,30);
    printf("%d\n",obj_b.value(&obj_a));
    return 0;
}

Автор: _GRIN_ 8.12.2011, 04:07
rumit7, спасибо за ссылку в стандарте =)

newbee, и тебе спасибо

baldina, и тебе =)

Тема закрыта

Автор: baldina 8.12.2011, 10:16
Цитата(_GRIN_ @  8.12.2011,  03:51 Найти цитируемый пост)
baldina, gcc твой пример не компилит

ну так саму переменную где-то определить надо
http://liveworkspace.org/code/fadab919a60a031828789c3d6b4e8c83

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)