Lippman第五名 ISBN-13:978-0321714114
第280-281页,它说:
让会员成为朋友
而不是让整个Window_mgr类成为朋友,Screen可以 而是指定只允许clear成员访问。什么时候我们 声明一个成员函数成为朋友,我们必须指定类的 哪个功能是成员:
class Screen { // Window_mgr::clear must have been declared before class Screen friend void Window_mgr::clear(ScreenIndex); // ... rest of the Screen class };
使成员函数成为朋友需要仔细构建我们的 程序,以适应声明和之间的相互依赖关系 定义。在这个例子中,我们必须按如下方式订购我们的程序:
- 首先,定义Window_mgr类,它声明但无法定义,清除。屏幕必须在清除之前声明才能使用 屏幕成员。
- 接下来,定义类屏幕,包括明确的朋友声明。
- 最后,定义clear,现在可以引用Screen中的成员。
问题是:类Window_mgr有一个依赖于类的数据成员 屏幕定义。参见:
class Window_mgr {
public:
// location ID for each screen on the window
using ScreenIndex = std::vector<Screen>::size_type;
// reset the Screen at the given position to all blanks
void clear(ScreenIndex);
private:
std::vector<Screen> screens{Screen(24, 80, ' ')};
};
因此,在不定义Screen的情况下首先定义Window_mgr是不可能的 先前! 而与此同时,没有我们就不可能定义屏幕 定义了Window_mgr !!!
如何解决这个问题? 这本书错了吗?
我会在这里粘贴代码,以便您可以使用a重复此问题 最小代码:
#include <iostream>
#include <string>
#include <vector>
class A
{
friend void B::hello();
public:
A(int i) : number{i} {}
private:
void f() {
std::cout << "hello" << std::endl;
}
int number;
};
class B {
private:
std::vector<A> x{A(10)};
public:
void hello()
{
for(A &elem : x)
{
elem.f();
}
}
};
int main()
{
A x;
return 0;
}
如果我编译此代码,结果是: 错误:使用未声明的标识符&#39; B&#39; friend void B :: hello();
如果我反转位置(A&lt; - &gt; B),我有: 错误:使用未声明的标识符&#39; A&#39; std :: vector x {A(10)};
有没有正确的方法呢?
谢谢!
编辑:
谢谢你,Craig Young
解决方案:
#include <iostream>
#include <string>
#include <vector>
class A;
class B {
private:
std::vector<A> x;
public:
B();
void hello();
};
class A
{
friend void B::hello();
public:
A(int i) : number{i} {}
private:
void f() {
std::cout << "hello" << std::endl;
}
int number;
};
B::B() : x{A(10)}
{
}
void B::hello()
{
for(A &elem : x)
{
elem.f();
}
}
int main()
{
return 0;
}
结论:
答案 0 :(得分:1)
您必须拥有较早的声明,但不能使用早期的定义。
添加
class A;
class B;
前面的告诉编译器“A”和“B”指的是类。这应该足以让其他人去推理。
答案 1 :(得分:1)
嗯,你没有正确遵循指导。
首先,定义Window_mgr类,它声明但不能定义,清除。必须在clear之前声明屏幕才能使用Screen的成员。
您必须在B
之前声明A
。
接下来,定义类屏幕,包括明确的朋友声明。
现在宣布A
与B::hello()
为好友。
最后,定义clear,现在可以引用Screen中的成员。
B:hello()
可以使用A
的私人成员。
此处已涵盖此内容:C++ Forward declaration , friend function problem
此外,您希望B
的声明引用A
。要实现这一目标,您需要转发声明A
,以便B
知道它的存在。
和 了解您只能“部分”访问A
非常重要。您无法在A
的声明中“完全使用”B
。因此B
中的以下行是错误的。
//You're trying to create A when you only know it exists.
//You don't have a full definition of A yet.
std::vector<A> x{A(10)};
//Replace the above with...
std::vector<A> x;
当然,你必须找到另一种方法来初始化x
。
#include <iostream>
#include <vector>
class A;
class B
{
private:
std::vector<A> x;
public:
void hello();
};
class A
{
friend void B::hello();
public:
A(int i): number(i) {}
private:
void f() { std::cout << "hello" << std::endl; }
int number;
};
void B::hello()
{
for(A &elem : x)
{
elem.f();
}
}
int main()
{
A a{5};
return 0;
}