Проблема с friend в c++

Вот пишу заголовочный файл:

#ifndef TEST_H_SENTRY
#define TEST_H_SENTRY

class ss1;
class ss2;

class ss1{
        int x1;
        void qwer1(ss2*);
public:
        friend void ss2::qwer2(ss1*);
};

class ss2{
        int x2;
        void qwer2(ss1*);
public:
        friend void ss1::qwer1(ss2*);
};

#endif

Компилятор пишет:

test.h:11:29: error: invalid use of incomplete type ‘class ss2’ friend void ss2::qwer2(ss1*);

test.h:5:7: note: forward declaration of ‘class ss2’ class ss2;

Не пойму в чем дело и как исправить. Помогите :-)


Ответы (4 шт):

Автор решения: AR Hovsepyan

Думаю вам нужно что то подобное:

class ss2;
class ss1 {
    int x1;
    //определение функции_члена написать после определения ss2
    static void qwer1(ss2*);
public:
    friend class ss2;    
};

class ss2 {
    int x2;
    //ss1 определен, можно написать определение
    static void qwer2(ss1* s) 
    {
        //...
    }
public:
    friend class ss1;   
};
void ss1::qwer1(ss2* s)
{
    //...
}

p.s. пока неизвестны точные намерения(для чего эти функции), ответ будет только примерным. Если хотите только функцию_член объявить другом, то класс должен быть уже определен, и функция_член должна быть общедоступным:

class ss2;
class ss1 {
    int x1;
public:    
    void qwer1(ss2*){} 
    // friend  void ss2::qwer2(ss1*);
    //это вы не сможете объявить, так как ss2 еще не определен
};

class ss2 {
    int x2;
public: 
    void qwer2(ss1*) {}
    friend  void ss1::qwer1(ss2*); //можно
};
→ Ссылка
Автор решения: Mikhailo

Циклическая проблема (курицы и яйца) - А обращается к Б, а потому Б должно быть раньше А, а Б обращается к А, а потому А должно быть раньше Б. Поэтому в рамках поставленной задачи решения нет.

→ Ссылка
Автор решения: TigerTV.ru

А как насчет использования nested classes? friend используется только для методов.

#ifndef TEST
#define TEST

#include <iostream>

class E {
private:
    E();
public:
    class I;
    class K;

private:
    static void printI(I* i) {
        std::cout << i->y << std::endl;
    }

    static void printK(K* k) {
        std::cout << k->y << std::endl;
    }
public:

    class I {
    private:
        int y;
        friend void E::printI(I* i);
    public:
        I(int x) {this->y = x;}
        void printFriend(K* k) {
            E::printK(k);
        }
    };

    class K {
    private:
        int y;
        friend void E::printK(K* k);
    public:
        K(int x) {this->y = x;}
        void printFriend(I* i) {
            E::printI(i);
        }
    };

};

#endif
→ Ссылка
Автор решения: AlexGlebe

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

// g++ -c -Wall -Wextra -Wpedantic -std=c++11 frinamspa4.hpp
#ifndef TEST_H_SENTRY
#define TEST_H_SENTRY

class ss1 ;
class ss2 ;

class friends {
  // для защиты от создания пустого абстрактного объекта
  friends ( void ) { } 
protected :
  // статический вариант для правильных типов
  static  void qwer2  ( ss2 & , ss1 * ) ;
  static  void qwer1  ( ss1 & , ss2 * ) ;
} ;

class ss1 : protected friends {
  int x1;
  friend friends ;
  void qwer1(ss2*);
public:
  void test(ss2 * s2) {
    qwer2 ( * s2 , this ) ; }
} ;

class ss2 : protected friends {
  int x2;
  friend friends ;
  void qwer2(ss1*);
public:
  void test(ss1 * s1) {
    qwer1 ( * s1 , this ) ; }
} ;

void friends::qwer2  ( ss2 & me , ss1 * const s1 ) {
  me . qwer2 ( s1 ) ; }
    
void friends::qwer1  ( ss1 & me , ss2 * const s2 ) {
  me . qwer1 ( s2 ) ; }
  
#endif
→ Ссылка