0

我正在尝试从特定类强制调用函数。例如,下面的代码演示了我的问题。我想让“使用”函数只能从 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();
}

bh

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

任何人都可以在这里帮忙吗?

非常感谢,

麦克风。

4

3 回答 3

2

这是因为在朋友声明中,您指的是班级成员。

为此,编译器必须已经看到 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&); 
}
}

bh

// 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();
}
于 2012-10-01T18:01:22.160 回答
1

以下从 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 类的“ah”中包含“bh”,但 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;

应该允许您的代码编译。

于 2012-10-01T18:14:29.240 回答
0

在第一个指令之后移动#include "b.h"from 。编译器在编译声明适用的函数之前不需要查看友元声明。a.ha.cpp#include

于 2012-10-01T17:59:55.023 回答