友元声明阻止外部函数访问类的私有部分

friend declaration block an external function access to the private section of a class

本文关键字:访问 声明 外部 函数 友元      更新时间:2023-10-16

我试图强制函数调用程序来自特定的类。例如,下面的代码演示了我的问题。我想让"use"函数只能从类A中调用。我在整个项目中使用全局命名空间。

a.h

#include "b.h"
namespace GLOBAL{
class A{
public:
void doSomething(B);
}
}

a.cp

#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

这里有人能帮忙吗?

非常感谢

迈克。

这是因为在朋友delcaration中,您引用的是一个类的成员。

为了使其工作,编译器必须已经看到A.的完整定义

a.h

// #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();
}

以下从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();
}

我可以告诉你,你的问题源于这样一个事实,即在定义a类之前,你包含了定义b类的"a.h"中的"b.h",而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;

应该允许您的代码进行编译。

在第一个#include指令之后将#include "b.h"a.h移动到a.cpp。编译器不需要看到友元声明,直到它编译了声明所应用的函数