Я пытаюсь заставить функцию звонящего из определенного класса.
Например, этот код ниже демонстрирует мою проблему.
Я хочу, чтобы функция ‘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
Кто-нибудь может здесь помочь?
Большое спасибо,
Майк.
Следующее хорошо компилируется из файла 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;
должен позволить вашему коду компилироваться.
Это потому, что в 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&);
}
}
// 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();
}
#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();
}
Переехать #include "b.h"
от a.h
в a.cpp
после первого #include
директивы. Компилятору не нужно видеть объявление друга, пока он не скомпилирует функцию, к которой применяется объявление.