返回信息流```cpp
#include <iostream>
class Display; // forward declaration for class Display
class Storage
{
private:
int m_nValue {};
double m_dValue {};
public:
Storage(int nValue, double dValue)
: m_nValue { nValue }, m_dValue { dValue }
{
}
// Make the Display::displayItem member function a friend of the Storage class
friend void Display::displayItem(const Storage& storage); // error: Storage hasn't seen the full definition of class Display
};
class Display
{
private:
bool m_displayIntFirst {};
public:
Display(bool displayIntFirst)
: m_displayIntFirst { displayIntFirst }
{
}
void displayItem(const Storage& storage)
{
if (m_displayIntFirst)
std::cout << storage.m_nValue << ' ' << storage.m_dValue << '\n';
else // display double first
std::cout << storage.m_dValue << ' ' << storage.m_nValue << '\n';
}
};
```
上面是某教程上的一个例子,目的就是`class Display`里有一个`member function displayItem`想要成为`Storage`的`friend function`,但是,教程说:
However, it turns out this won’t work.
In order to make a member function a friend,
the compiler has to have seen the full definition for the class of the friend member function (not just a forward declaration).
求问:
- 为啥`the compiler has to have seen the full definition for the class`?
- 有些时候,`class` 不是只需要提供一个 `forward declaration`就行了吗?
这是一条镜像帖。来源:北邮人论坛 / cpp / #102064同步于 2022/8/8
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
【问题】friend member functions
YiYeShu
2022/8/8镜像同步3 回复
订阅后,新回复会通过你的通知中心匿名送达。
3 条回复
前向声明的类型为不完整类型,编译器对不完整类型的大小、成员一无所知。我觉得编译器在读到"Display::displayItem"时,会做name lookup的操作,前向声明告诉了编译器“Display”是一个类,由于在这行代码之前,编译器没有读到关于“Display”的内部细节,所以在找“displayItem”时就会出错。不完整类型的使用具有一定的限制,例如说不完整类型只能出现在指针、引用定义等,具体参见“https://stackoverflow.com/a/553869/18284218”。PS:由于还没学到编译原理相关知识,因此不能从更底层的角度回答
编译器无法在仅仅已知class Display这样的不完整声明的前提下获得Display::displayItem
也就是说,在Display完整声明的情况下才能使用Display::displayItem
需要稍微对声明与定义的顺序进行调整,解除循环依赖
```C++
#include <iostream>
class Storage; // forward declaration for class Display
class Display
{
private:
bool m_displayIntFirst {};
public:
Display(bool displayIntFirst)
: m_displayIntFirst { displayIntFirst } {}
void displayItem(const Storage& storage);
};
class Storage
{
private:
int m_nValue {};
double m_dValue {};
public:
Storage(int nValue, double dValue)
: m_nValue { nValue }, m_dValue { dValue }
{
}
// Make the Display::displayItem member function a friend of the Storage class
friend void Display::displayItem(const Storage& storage); // error: Storage hasn't seen the full definition of class Display
};
void Display::displayItem(const Storage& storage) {
if (m_displayIntFirst)
std::cout << storage.m_nValue << ' ' << storage.m_dValue << '\n';
else // display double first
std::cout << storage.m_dValue << ' ' << storage.m_nValue << '\n';
}
```