Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 作为朋友的成员功能:Lippman 5th这本书错了吗?_C++ - Fatal编程技术网

C++ 作为朋友的成员功能:Lippman 5th这本书错了吗?

C++ 作为朋友的成员功能:Lippman 5th这本书错了吗?,c++,C++,利普曼5号 ISBN-13:978-0321714114 第280-281页,上面写着: 让会员成为朋友 Screen可以使整个Window_mgr类成为朋友,而不是成为朋友 而是指定只允许clear成员访问。当我们 声明一个成员函数为友元,我们必须指定 哪个职能部门是成员: class Screen { // Window_mgr::clear must have been declared before class Screen friend void Window_mgr:

利普曼5号 ISBN-13:978-0321714114

第280-281页,上面写着:

让会员成为朋友

Screen可以使整个Window_mgr类成为朋友,而不是成为朋友 而是指定只允许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。必须先声明屏幕,然后clear才能使用 银幕成员
  • 接下来,定义类屏幕,包括用于清除的好友声明
  • 最后,定义clear,它现在可以引用屏幕中的成员
问题是:类窗口\u 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, ' ')};
};
类窗口\u管理器{
公众:
//窗口上每个屏幕的位置ID
使用ScreenIndex=std::vector::size\u type;
//在给定位置将屏幕重置为所有空白
空白清除(屏幕索引);
私人:
病媒筛选{Screen(24,80,')};
};
因此,在不定义屏幕的情况下,首先定义窗口管理器是不可能的 以前! 同时,如果没有我们的帮助,就不可能定义屏幕 已定义的窗口管理器

这个问题怎么解决??? 这本书错了吗

我将在这里粘贴一个代码,以便您可以使用 最小代码:

#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;
}
#包括
#包括
#包括
甲级
{
朋友B::你好();
公众:
A(inti):数{i}{}
私人:
void f(){

std::cout您必须有一个更早的声明,但不能有一个更早的定义

添加

class A;
class B;
前面的代码告诉编译器“A”和“B”引用类。这应该足以让它推断出其余的部分。

作为开始 嗯,你没有正确地遵循指南

首先,定义Window_mgr类,该类声明但不能定义clear.Screen,在clear可以使用Screen的成员之前,必须声明Screen

您必须在
A
之前声明
B

接下来,定义类屏幕,包括用于清除的好友声明

现在将
A
B::hello()
声明为朋友

最后,定义clear,它现在可以引用屏幕中的成员

B:hello()
可以使用
A
的私有成员

在此之前已经介绍过:

你增加了复杂性 此外,您希望
B
的声明引用
A
。为此,您需要转发declare
A
,以便
B
知道它的存在

必须意识到,您只能“部分”访问
A
。您不能在
B
的声明中“完全使用”
A
。因此
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;

此解决方案无效:错误:嵌套名称说明符friend void B::hello()中命名的类型“B”不完整;在A/B示例中,除了friendless之外,您还有其他问题,因为您包含了方法体,因此需要实现细节,而不仅仅是类签名。这就是类通常在头文件中定义其签名的原因。如果删除方法体,则数据成员std::vector x{A(10) }来解决。这本书忽略了这个问题。数据成员本身很好,它是一个核心调用,给它一个循环引用的值。把它放在类签名之后提供的ctor体中。我试图在a之前声明B,但我没有注意到问题是a(10),而不是向量!也就是说,我们可以使用不完整的类型a(仅声明,无定义)将其用作向量的模板参数时(因为它本身不创建对象)但是,在定义对象时,我们不能使用不完整的类型A,例如:A u;我将编辑我的问题并接受您的回答。谢谢!当您说我增加了复杂性时,我不同意您的说法。请参阅std::vector screens{Screen(24,80,')}行;也就是说,这本书是不完整的,因为它没有揭示进行A类正向声明的必要性以及在这种情况下不可能进行类内初始化。我的编辑更正了这两个问题。再次感谢。
//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;
#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;
}