2013-11-09 3 views
0

У меня есть два класса Screen и Window_Mgr (C++ Primer 5th Edition Chapter 7).включают классы в файлы заголовков в других файлах заголовков

  1. Экран представляет собой класс, который содержит три строки :: size_types и строку в качестве элементов данных.
  2. Window_Mgr это класс, который содержит объект экранов типа вектора < экрана>.
  3. инициализирует вектор < экрана> со значениями (24,80,»«) с конструктором в экране.
  4. void Window_Mgr :: clear (vector :: size_type i) - это функция, которая обращается к закрытым членам строки и очищает их от всех данных.

Я хочу написать этот код таким образом, что только Window_Mgr :: clear является другом экрана.

Проблемы я столкнулся с являются:

  1. Если я определяю Window_Mgr перед тем экран с неполной декларации я не могу инициализировать экраны.
  2. Если я определяю экран перед Window_Mgr с неполным объявлением, я не могу объявить Window_Mgr :: clear в качестве друга Экран.

Я попытался включить их с отдельными файлами заголовков, но это был настоящий беспорядок.

#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; 
    } 
}; 

ответ

1

Вы нарушаете инкапсуляцию, имея Screen, звоните Window_Mgr.

Window_Mgr - это контейнер Screen с. 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.

+0

Спасибо за ответ! Я не получаю эти порции: 'Вы нарушаете инкапсуляцию, имея экранный вызов Window_Mgr.' Если вы имеете в виду эту строку' friend void Window_Mgr :: clear (Screen_Index i); 'Я вызываю функцию-член Window_Mgr .. Разве это не разрешено? 'Кроме того, класс Screen не должен знать, находится ли он в контейнере или нет; эта концепция принадлежит классу Window_Mgr' Как класс знает, является ли это контейнером? – Deohboeh

+0

Подумайте, почему 'Screen' нужно вызвать' Window_Mgr'? Это означает, что объект «Screen» знает о своем контейнере. Все, что связано с 'Screen', принадлежит' Screen', а не 'Window_Manager'. –

+0

Идея довольно расплывчата в моей голове, но насколько я понимаю ... 'Window_Mgr :: Screens' - это контейнер' Screen' и в ясном func Я вызываю экран, чтобы очистить элементы 'Window_Mgr :: Screens 'и не вызывать экран, чтобы очистить свои собственные члены через свою собственную функцию, которая делает ее менее модульной? O_O '* Пожалуйста, проявляйте терпение, я могу быть немым, как ... Но я хотел бы это понять ... – Deohboeh

1

Рассмотрите возможность использования классов, а ваше прямое объявление относится к классу, в котором вы создаете экран как структуру. Это может вызвать некоторые из ваших проблем. и вместо того, чтобы использовать друга, как о двух отдельных четких функциях, один для Window_mgr, который вызывает другую четкую функцию в Экран.

ваш window_mgr ясно будет что-то вроде

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

и ваш экран ясно будет что-то вроде

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

И как один из моих профессоров вбить в наши головы «друзей классов не друзья программистов "

+0

Можете ли вы привести языковой стандарт, в котором 'public' и' private' не имеют значения для структур? Единственная разница, в C++, между 'struct' и' class' - это доступность по умолчанию. Для 'struct' доступность по умолчанию -' public', а для 'class' -' private'. –

+0

Я ошибался, что в c ... иногда я смущаюсь. Спасибо, что указали мою ошибку. Я отредактировал ответ – thermite

+0

Спасибо! Я буду держать в виду, что «Друзья классов не друзья программистов»! : D – Deohboeh

Смежные вопросы