объявление друга блокирует доступ внешней функции к закрытому разделу класса

Я пытаюсь заставить функцию звонящего из определенного класса.
Например, этот код ниже демонстрирует мою проблему.
Я хочу, чтобы функция ‘use’ вызывалась только из класса A.
Я использую глобальное пространство имен по всему проекту.

хиджры

#include "b.h"namespace GLOBAL{

class A{
public:
void doSomething(B);
}
}

a.cpp

#include "a.h"using namespace GLOBAL;

void A::doSomething(B b){

b.use();
}

b.h

namespace GLOBAL{

class B{
public:
friend void GLOBAL::A::doSomething(B);
private:
void use();
}

Компилятор говорит:

‘GLOBAL::A’ has not been declared

‘void GLOBAL::B::use()’ is private

Кто-нибудь может здесь помочь?

Большое спасибо,

Майк.

0

Решение

Следующее хорошо компилируется из файла cpp:

namespace GLOBAL
{
class B;

class A
{
public:
void doSomething(B& b);
};
};namespace GLOBAL
{
class B
{
public:
friend void GLOBAL::A::doSomething(B&);
private:
void use()
{
}
};
};

void GLOBAL::A::doSomething(B& b)
{
b.use();
}

Насколько я могу судить, ваша проблема возникает из-за того, что вы включили «b.h» из «a.h», который определяет класс B до того, как класс A определен, а класс B ссылается на класс A. Итак, у вас есть проблемы. Однако вы не можете форвард объявить объект типа B, потому что вы копируете через стек. Следовательно, почему я использую ссылку на класс B (поскольку это не требует, чтобы объект B был известен заранее).

По сути, у вас есть некоторые фундаментальные проблемы с вашей структурой, которые нужно проработать. Вам нужно немного почитать предварительные декларации а также круговые зависимости

редактировать: Указание чисто того, что класс A является другом B (а не конкретной функцией в A, которая ссылается на B), на самом деле возможно, так как определение друга обеспечивает своего рода предварительное объявление. Таким образом, следующий код компилируется:

namespace GLOBAL
{
class B
{
public:
friend class A;
private:
void use()
{
}
};
};

namespace GLOBAL
{
class A
{
public:
void doSomething(B b);
};
};

void GLOBAL::A::doSomething(B b)
{
b.use();
}

Как таковой в вашем коде, первоначально опубликованном, просто подгоняя заявление друга,

friend class A;

должен позволить вашему коду компилироваться.

1

Другие решения

Это потому, что в delcaration друга вы ссылаетесь на члена класса.

Чтобы это работало, компилятор уже должен видеть полное определение A.

хиджры

// #include "b.h"   // remove this line it is not needed.
namespace GLOBAL{

class B; // Forward declare the class here.

class A{
public:
void doSomething(B&); // Note: This should probably be a reference.
// Change to doSomething(B&);
}
}

b.h

// Add this line it is needed for the friend declaration.
// To have a member as a friend we need the definition of 'A'
#include "a.h"
namespace GLOBAL{

class B{
public:
friend void GLOBAL::A::doSomething(B&);
private:
void use();
}

a.cpp

#include "a.h"// Add this line to include the B definition so you know how to call use()
#include "b.h"using namespace GLOBAL;

void A::doSomething(B& b){ // b should be a reference otherwise you are copying it.

b.use();
}
2

Переехать #include "b.h" от a.h в a.cpp после первого #include директивы. Компилятору не нужно видеть объявление друга, пока он не скомпилирует функцию, к которой применяется объявление.

0
По вопросам рекламы [email protected]