通过友元成员函数访问受保护的数据成员

3

编辑:

原始程序有多个文件,如此处所示

我正试图从一个不同的类的友元成员函数中访问我的类中受保护的数据成员。

我一直得到一个访问错误:

9:32:错误:无效使用未完成的类型“b类”5:7:错误:前向声明“b类”在成员函数“void b::f(a *)”中:12:13:错误:“int a :: i”受保护20:47:错误:在此上下文中

这是我的代码:

// Example program
#include <iostream>
#include <string>

class b;
class a{
    public:
    
    friend void b::f(a* pointer);
    
    protected:
    int i = 6;
    
    
    
};

class b{
    public:
    void f(a* pointer){std::cout<<pointer->a::i<<std::endl;}
    
    
};




int main()
{
  a a1;
  b b1;
  
  b1.f(&a1);
}

声明b::f()friend,需要先定义类b。仅有一个简单的class b声明是不够的。 - Peter
@Peter,但如果两个类相互依赖,我该怎么办? - oded
在定义类b之前,先声明类a。然后在类a之前而不是之后定义类b。您还需要将b::f()的定义移动到类定义之外(而不是内联)。 - Peter
但如果两个类是相互依赖的,我该怎么办?更改您的设计,使它们不再相互依赖。有许多解决方案,这取决于实际目标是什么... - 463035818_is_not_a_number
3个回答

3
问题只是表面上与“friend”有关。实际上,它是由类定义和成员函数之间的循环依赖所引起的;a需要知道b的定义,因为它引用b::f。但是,b::f的定义需要a的定义,因为它引用a::i。幸运的是,类及其成员函数的定义可以相互分离。
您可以采取以下步骤逐步解决该问题:
  1. 声明class a;
  2. 定义class b { /* ... */ };,但不要定义其成员函数(因为它们需要访问a的定义)
  3. 定义class a { /* ... */ };,可能包含内联成员函数的定义
  4. 最后定义b的成员函数。
下面是示例代码:
// Step 1:
class a;

// Step 2:   
class b{
    public:
    void f(a* pointer);
};

// Step 3:
class a{
    public:
    friend void b::f(a* pointer);
    
    protected:
    int i = 6;
};

// Step 4:
void b::f(a* pointer)
{
    std::cout<<pointer->a::i<<std::endl;
}

感谢您的回复。为什么这里不起作用? - oded
因为你误解了步骤1,所以你的头文件仍然存在循环依赖。b.h 包含 a.h,但它必须声明 class a; 而不是包含其完整定义。 - lubgr

1
当你尝试通过 friend void b::f(a* pointer); 声明 b 类的方法为友元时,b 类是不完整的。你还不能引用其中的成员。另一方面,b 类只需要对 a 进行前向声明:
// Example program
#include <iostream>
#include <string>

class a;
class b{
    public:
    void f(a* pointer);                
};

class a{
    public:        
    friend void b::f(a* pointer);        
    protected:
    int i = 6;
};

void b::f(a* pointer){std::cout<<pointer->a::i<<std::endl;}

int main()
{
  a a1;
  b b1;
  
  b1.f(&a1);
}

1

试试这个。你正在尝试在定义类 b 之前引用 b::f

// Example program
#include <iostream>
#include <string>
class a;

class b{
    public:
    void f(a* pointer);
};
class a{
    public:
    
    friend void b::f(a* pointer);
    
    protected:
    int i = 6;        
};

void b::f(a* pointer)
{std::cout<<pointer->a::i<<std::endl;}






int main()
{
  a a1;
  b b1;
  
  b1.f(&a1);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接