Расширение класса
РЕДАКТИРОВАТЬ ОТВЕТ: Хотя мой первоначальный вопрос не объяснял мои потребности в точности так, как на них ответил ответ Конрада Рудольфа, он (случайно или намеренно), по сути, написал для меня то, что я пытался написать! Сам класс не расширяется, но его функциональность расширяется за счет информирования класса о новых функциях, которые позволяют ему (классу) обрабатывать более широкий круг вопросов. Я благодарен за отличный ответ, который, в свою очередь, также является отличным учебником, даже если он требует некоторого света ahemm? чтение книг мной;-).
Я уверен, что это очень простой вопрос, но я пытаюсь самостоятельно учить C++, и справочники, которые я использую, дают ответы, которые я не понимаю.
Для моего проекта я определяю class error_handler {}
который обрабатывает сообщения об исключениях и номера ошибок от программ различных точек. Он записывает ошибку в файл и / или выводит сообщение на экран, используя различные функции-члены.
Моя цель состоит в том, чтобы создать его так, чтобы он имел свои собственные файлы.h и.cpp, и, если мне позже понадобится его расширить, просто добавьте новую функцию-член для обработки более неясного типа обработки ошибок.
Мой вопрос тогда такой:
Так как в error.h
У меня есть код:
class error_handler
{
// ctor dtor copy logger screen functions defined
}
И в error_handler.cpp
Я дополняю эти определения,
Как я могу просто добавить новую функцию в класс? Я не хочу подкласса это, просто расширить его.
В сценарии использования предположим, что error_handler - это класс, определенный в проприетарном пакете, где я не могу напрямую изменять исходный код, но мне разрешено расширять его в отдельном коде.
РЕДАКТИРОВАТЬ: ответы и комментарии до сих пор, кажется, указывают, что я пытаюсь сделать что-то, что язык не предназначен, чтобы сделать. Если так, то пусть будет так, я кое-чему научился здесь. В надежде, что это не так, я оставлю вопрос открытым, чтобы посмотреть, что еще может появиться на этом посте......
3 ответа
Это во многом зависит от того, что это за функции. Учитывая ваше приложение, я пойду дальше и предположу, что функции, которые вы хотите добавить, существуют для обработки дополнительных типов ошибок.
Для простоты, давайте предположим, что каждая функция (давайте назовем ее handle
) просто передается объект ошибки, который он анализирует и либо обрабатывает, либо не обрабатывает. Возвращает bool
чтобы указать это.
Тогда вы могли бы иметь следующее (упрощенно) error_handler
учебный класс:
class error_handler {
public:
using handler_t = bool (*)(error const&);
std::vector<handler_t> handlers;
// …
void add_handler(handler_t handler) {
handlers.push_back(handler);
}
void handle_error(error const& error) {
for (auto const& handler : handlers)
if (handler(error))
break;
}
};
Это предполагает, что ваши ошибки представлены экземпляром класса error
(и что вы используете C++11 - синтаксис немного меняется в противном случае).
Теперь это определение класса исправлено. Вы можете добавить другие обработчики, определенные в других файлах, просто вызвав add_handler`. Вот два примера:
// Simple logging “handler”. Needs to be added first!
extern error_handler global_error_handler;
bool log_handler(error const& error) {
std::cerr << error.message() << '\n';
return false; // We only log, we don’t handle.
}
global_error_handler.add_handler(log_handler);
// Handler for missing dog food
extern error_handler global_error_handler;
errno_t const MISSING_DOG_FOOD = 42;
bool dog_food_missing(error const& error) {
if (error.code() != MISSING_DOG_FOOD)
return false;
global_dog_food_container.add(some_food());
return true;
}
global_error_handler.add_handler(dog_food_missing);
В C++ вы не можете изменить класс без изменения class
заблокировать и добавить определение вашей функции (т.е. в error.h
)
Если вы не можете изменить файл заголовка, тогда ваши единственные варианты - либо наследовать класс, либо написать функции, не являющиеся членами, которые работают с классом (но они смогут видеть только открытые члены)
Единственный способ расширить класс без изменения его исходного определения - создать новый класс, производный от него. Возможно, вы должны быть более конкретными с тем, что вы пытаетесь сделать. Имеет ли существующий код, который использует error_handler
должны быть затронуты ваши изменения? Например, если вы просто хотите добавить функцию, которая будет регистрировать ошибку другим способом, и собираетесь использовать эту функцию только в своем новом коде, вы можете создать обычную функцию, не являющуюся членом, которая принимает ссылку error_handler
, но более чистым способом было бы создать my_error_handler
(производный) класс с новым методом. Указатель / ссылка на экземпляр my_error_handler
может быть свободно преобразован в указатель / ссылку на error_handler
если вы хотите передать его в существующий код.