友元函数的前向声明:不完整类型的无效使用

7
#include <iostream>

class B;

class A{
 int a;
public:
 friend void B::frndA();
};

class B{
 int b;
public:
 void frndA();
};

void B::frndA(){
 A obj;
 std::cout << "A.a = " << obj.a << std::endl;
}

int main() {
 return 0;
}

在尝试编译这段代码时,出现了一些错误。例如:

不完整类型的无效使用

这段代码存在哪些问题?


2
我已经重新标记了这个问题。friend 不是最有帮助的关键字之一。此外,forward-declaration 结合在一个标签中更有意义。编辑:哦,我想 class 也比 function 更有意义 :) - Ivo Wetzel
3个回答

3
将整个 class B ... 的声明放在 class A 之前。你还没有声明 B::frndA();
#include <iostream>
using namespace std;

class B{
    int b;
public:
    void frndA();
};

class A{
    int a;
public:
    friend void B::frndA();
};



void B::frndA(){
    A obj;
    //cout<<"A.a = "<<obj.a<<endl;
}

int main() {
    return 0;
}

3
问题在于,在编译器看到声明之前,无法将成员函数定义为友元函数。
你需要重新排列代码以解决这个问题(即在class A之前定义class B)。

2
你需要先声明 B 再声明 A。编译器不会知道这个: B::frndA()。前向声明并不能提供足够的信息来推断类型有哪些成员。
我建议你将类 A 的声明放在文件 A.h 中,将它的定义放在文件 A.cpp 中;同样地,将类型 B 放在文件 B.hB.cpp 中。
在每个头文件的顶部加上 #pragma once(或者如果你喜欢,使用 include guards)。
然后在 B.h 中,你可以简单地包含 A.h

1
事实上,#pragma once 可能会失败,因为它是基于文件路径而不是文件内容,所以当同一文件位于不同的搜索路径中时,可能会出现问题。 - Edward Strange
#pragma once被所有主要的编译器支持。我认为#pragma once不应该被贬低。请参见这里:https://dev59.com/gXM_5IYBdhLWcg3w-4dg#1143958 - Brian R. Bondy

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