#c
Вопрос:
В главе 7.3.4 книги C Primer упоминаются прямые объявления и указание друзей функций-членов. В нем говорится, что определение друзей функций-членов требует тщательной структуры для учета взаимозависимости между объявлениями и определениями. Когда я снимаю весь пух, вот результат:
#include <string>
#include <vector>
class Screen;
class Window_mgr {
public:
using ScreenIndex = std::vector<Screen>::size_type;
void clear(ScreenIndex);
private:
std::vector<Screen> screens;
};
class Screen {
friend void Window_mgr::clear(ScreenIndex);
public:
using pos = std::string::size_type;
private:
pos height{0},
width{0};
std::string contents;
};
inline void Window_mgr::clear(ScreenIndex i) {
Screenamp; s = screens[i];
s.contents = std::string(s.height * s.width, ' ');
}
Насколько я понимаю, классы помещаются в свои собственные заголовочные файлы. Если это так, то как мне их разделить? Я проверил некоторые вопросы о переполнении стека, но не нашел ответа, который ищу.
Правка: вот как мне удалось очистить код, но я все еще не уверен, хорошо ли это из-за плохой практики и возможно ли это вообще поддерживать.
window_mgr.h
#ifndef WINDOW_MGR_H
#define WINDOW_MGR_H
#include <vector>
class Screen;
class Window_mgr {
public:
using ScreenIndex = std::vector<Screen>::size_type;
void clear(ScreenIndex);
private:
std::vector<Screen> screens;
};
#endif
screen.h
#ifndef SCREEN_H
#define SCREEN_H
#include <string>
#include "window_mgr.h"
class Screen {
friend void Window_mgr::clear(ScreenIndex);
public:
using pos = std::string::size_type;
private:
pos height{0},
width{0};
std::string contents;
};
#endif
window_mgr.cpp
#include "window_mgr.h"
#include "screen.h"
inline void Window_mgr::clear(ScreenIndex i) {
Screenamp; s = screens[i];
s.contents = std::string(s.height * s.width, ' ');
}
Комментарии:
1.
void Window_mgr::clear(ScreenIndex i)
вошел бы в Window_mgr.cpp2. Возьмите объявление класса в заголовок и определение методов в файле cpp. В большинстве случаев у вас будет меньше проблем с включениями, когда каждый класс находится в отдельном .h/.cpp файл.
3. «Насколько я понимаю, классы помещаются в свои собственные заголовочные файлы». Необязательно. C — это не Java. Вы можете разместить в одном заголовке столько классов, сколько захотите, и часто «по одному классу на файл» очень непрактично
4. @Jarod42 Зачем этой функции нужна собственная единица перевода?
5. Решение — избегайте друзей, позвольте
Screen
определить, как он очищается, и позвольтеWindow_mgr
использовать эту общедоступную функциональностьScreen
Ответ №1:
Как бы то ни было…
Мне никогда не приходилось использовать методы друзей, кроме оператора< Если вы добавляете геттеры в личные поля, то вашему методу Window_mgr не обязательно быть другом, и вы устраняете циклическую зависимость.