Проблема с 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 шт):
Думаю вам нужно что то подобное:
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*); //можно
};
Циклическая проблема (курицы и яйца) - А обращается к Б, а потому Б должно быть раньше А, а Б обращается к А, а потому А должно быть раньше Б. Поэтому в рамках поставленной задачи решения нет.
А как насчет использования 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
Выборочное разрешение методов двух классов друг другу можно реализовать с помощью базового класса. Этот класс будет содержать только эти функции. И защита будет стандартной. Этим функциям будет разрешён доступ к двум классам. И вызывать эти функции можно только внутри этих классов. Нужно сделать эти функции статическими, для того, чтобы тип объекта соответствовал имени функции.
// 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