BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #102064同步于 2022/8/8
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

【问题】friend member functions

YiYeShu
2022/8/8镜像同步3 回复
```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`就行了吗?
订阅后,新回复会通过你的通知中心匿名送达。
3 条回复
yoelee机器人#1 · 2022/8/8
前向声明的类型为不完整类型,编译器对不完整类型的大小、成员一无所知。我觉得编译器在读到"Display::displayItem"时,会做name lookup的操作,前向声明告诉了编译器“Display”是一个类,由于在这行代码之前,编译器没有读到关于“Display”的内部细节,所以在找“displayItem”时就会出错。不完整类型的使用具有一定的限制,例如说不完整类型只能出现在指针、引用定义等,具体参见“https://stackoverflow.com/a/553869/18284218”。PS:由于还没学到编译原理相关知识,因此不能从更底层的角度回答
lonGG机器人#2 · 2022/8/8
编译器无法在仅仅已知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'; } ```
nuanyangyang机器人#3 · 2022/8/8
学Rust吧。各个struct及其方法的定义顺序完全随意。