如何在类定义交叉引用时声明friend方法?

时间:2013-12-25 12:14:50

标签: c++ friend-function

我想定义两个类,A和B.A有一个数据成员,它是一个B类对象,并且是在类中初始化的。 A还有一个方法来检索这个B类型数据成员中的值,这个方法将在B中声明为友元方法。这是我的代码:

class A{
public:
    int getBValue();
private:
    B b=B(1);
};

class B{
public:
    friend int A::getBValue();
    B(int i):value(i){}
private:
    int value;
};

int A::getBValue(){
    return b.value;
}

不出所料,由于A类定义中B类未知,编译失败了。我试图在源中交换A和B的定义,结果更糟。有没有办法解决A和B之间的交叉引用问题?

2 个答案:

答案 0 :(得分:3)

如果这是完整的代码,那么问题是编译器在编译类B时不知道A是什么。解决这个问题的一种方法是创建一个指向B的指针而不是B本身:

<强> A.H

#ifndef CLASS_A
#define CLASS_A

class B;

class A{
public:
    int getBValue();
private:
    B *b;
};

#endif

<强> B.h

#ifndef CLASS_B
#define CLASS_B

#include "A.h"

class B{
public:
    friend int A::getBValue();
    B(int i):value(i){}
private:
    int value;
};

#endif

<强> A.cpp

#include "A.h"
#include "B.h"

int A::getBValue(){
    return b->value;
}

答案 1 :(得分:0)

B类型的嵌入式成员替换为B的指针(或引用)会改变类的工作方式,并且在复制类A的对象时需要额外注意。< / p>

当你颠倒定义时,你不能使类A的成员函数成为类B的朋友,因为A的类型在{friend时是不完整的。 1}}声明。但是你可以让整个班级A成为朋友。

具有类A的嵌入成员的类B的解决方案可能如下所示:

class A;

class B{
public:
    friend class A;
    B(int i):value(i){}
private:
    int value;
};

class A{
public:
    int getBValue();
private:
    B b=B(1);
};

int A::getBValue(){
    return b.value;
}

所做的更改:

  1. B之前声明A。使用了A的前瞻性声明。
  2. A设为B的朋友。即使尚未完全定义A,这仍然有效。
  3. 使用g ++版本4.7.2进行编译(B b=B(1);需要-std = c ++ 11)

    无论如何,让一个班级A的成员访问班级B的私人成员是可以(而且应该)几乎总能避免的事情(参见Laszlo Papp对你帖子的评论)。