【问题标题】:include classes in header files in other header files在其他头文件中包含头文件中的类
【发布时间】:2013-11-21 16:45:47
【问题描述】:

我有两个类 Screen 和 Window_Mgr(C++ Primer 5th Edition Chapter 7)。

  1. Screen 是一个包含三个 string::size_types 和一个 string 作为数据成员的类。
  2. Window_Mgr 是一个包含 vectorScreen> 类型的对象 Screens 的类。
  3. 它使用 Screen 中的构造函数使用值 (24,80,' ') 初始化 vectorScreen>。李>
  4. void Window_Mgr::clear(vector::size_type i) 是一个访问字符串私有成员并清除所有数据的函数。

我想以只有 Window_Mgr::clear 是 Screen 的朋友的方式编写此代码。

我面临的问题是:

  1. 如果我在 Screen 之前使用不完整的声明定义 Window_Mgr,我将无法初始化 Screens
  2. 如果我在 Window_Mgr 之前使用不完整的声明定义 Screen,我无法将 Window_Mgr::clear 声明为 Screen 的朋友。

我尝试将它们包含在单独的头文件中,但那真是一团糟。

#include <iostream>
#include <vector>

class Screen;

struct Window_Mgr{
public:
    //    using Screen_Index = std::vector<Screen>::size_type;
    typedef std::vector<Screen>::size_type Screen_Index;

    void clear(Screen_Index i);

    Window_Mgr() = default;

private:
    std::vector<Screen> Screens;
};



struct Screen{

    typedef std::string::size_type pos;

    friend void Window_Mgr::clear(Screen_Index i);

    Screen() = default;
    Screen(pos h, pos w, char s): height(h), width(w), contents(h*w,s){};

    char get() const { return contents[cursor];}
    char get(pos ht, pos width)const;
    Screen &move(pos r, pos c);
    Screen &set(char);
    Screen &set(pos, pos, char);
    Screen & display(std::ostream &);
    const Screen & display (std::ostream &) const;

    pos size() const;


private:
    pos cursor = 0;
    pos height = 0, width = 0;
    std::string contents;
    const Screen do_display (std::ostream& os) const
    {
        os << contents;
        return *this;
    }
};

【问题讨论】:

    标签: c++ header include forward-declaration


    【解决方案1】:

    考虑改用类,您的前向声明是针对一个类,您可以在其中将屏幕创建为一个结构。这可能会导致您的一些问题。与其使用朋友,不如使用两个单独的清除函数,一个用于 Window_mgr,它在 Screen 中调用不同的清除函数。

    您的 window_mgr clear 将类似于

    void Window_Mgr::clear(int i)
    {
        Screens.at(i).clear();
    }
    

    你的屏幕清晰会是这样的

    void Screen::clear()
    {
        //whatever you want to do to private variables here
    }
    

    正如我的一位教授在我们脑海中敲响的“课堂之友不是程序员之友”

    【讨论】:

    • 你能引用一个语言标准,其中publicprivate 对结构没有意义吗?在 C++ 中,structclass 之间的唯一区别是默认可访问性。对于struct,默认可访问性为public,对于class,默认可访问性为private
    • 我误认为是在 c... 有时我会感到困惑。感谢您指出我的错误,我已经编辑了答案
    • 谢谢!我会牢记“类的朋友不是程序员的朋友”! :D
    【解决方案2】:

    Screen 调用 Window_Mgr 违反了封装。

    Window_MgrScreens 的容器。 Window_Mgr 应该调用屏幕的clear 方法。

    struct Screen
    {
      void clear()
      {
         //...
      }
    };
    
    
    struct Window_Mgr
    {
      std::vector<Screen> Screen_Container;
      void clear_screen(unsigned int screen_index)
      {
        Screen_Container[screen_index].clear();
      }
    };
    

    由于简单起见,我没有对索引范围进行检查。

    编辑 1:友谊。
    这里不需要友谊。 Window_Mgr 只能访问 Screen 类在其接口中定义的内容。

    另外,Screen 类应该不知道它是否在容器中;该概念属于Window_Mgr 类。

    【讨论】:

    • 感谢您的回答!我没有得到这些部分:You are violating encapsulation by having Screen call Window_Mgr. 如果你的意思是这一行friend void Window_Mgr::clear(Screen_Index i); 我正在调用 Window_Mgr 的成员函数。这是不允许的吗? Also, the Screen class should have no knowledge of whether it is in a container or not; that concept belongs to the Window_Mgr class类怎么知道是不是容器?
    • 想一想,为什么Screen需要调用Window_Mgr?这意味着Screen 对象知道它的容器。任何与Screen 相关的东西都属于Screen 而不是Window_Manager
    • 这个想法在我脑海中非常模糊,但据我所知......Window_Mgr::ScreensScreen 的容器,并且在明确的功能中,我正在调用屏幕以清除Window_Mgr::Screens 的成员并且不调用 screen 通过它自己的函数来清除它自己的成员,这使得它的模块化程度降低了? O_O' *请耐心等待我可能很笨...但是我想了解这一点...
    • Window_Mgr 应该遍历向量或屏幕,为每个屏幕调用clear 方法。如果 Window_Mgr 需要清除其成员,它应该在自己的方法中执行此操作。 Screen 不应调用 Window_Mgr 中的任何函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    相关资源
    最近更新 更多