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

时间:2012-10-01 17:55:03

标签: c++ namespaces friend

我正试图强制来自特定类的函数调用者。 例如,此代码显示我的问题。 我想让“使用”功能只能从A类调用。 我在整个项目中使用全局命名空间。

A.H

#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

有人可以帮忙吗?

非常感谢,

麦克

3 个答案:

答案 0 :(得分:2)

这是因为在朋友退场时你正在引用一个班级的成员。

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

答案 1 :(得分: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类的“a.h”中加入了“b.h”而B类引用了A类。所以你有问题。但是,您无法转发声明类型B的对象,因为您正在通过堆栈进行复制。因此,为什么我使用对B类的引用(因为这不需要事先知道B对象)。

基本上你的结构存在一些基本问题需要解决。您需要在forward declarationscircular dependencies

上进行一些阅读

编辑:纯粹指定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;

应该允许你的代码编译。

答案 2 :(得分:0)

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