编辑回答:虽然我原来的问题并没有完全按照康拉德鲁道夫提供的答案解释我的需求,但他(偶然或设计)基本上是为我写了我想写的东西!类本身不会扩展,但通过使类知道允许它(类)处理更多问题的新函数来扩展它的功能。我非常感谢你给出了一个很好的答案,反过来也是一个很好的教程,即使它确实需要一些光线?我读书; - )。
我确信这是一个非常基本的问题,但我正在尝试自学C ++,我正在使用的参考书提供了我不理解的答案。
对于我的项目,我定义了一个class error_handler {}
,它从程序的各个点处理异常消息和错误号。它会将错误记录到文件中和/或使用各种成员函数将消息打印到屏幕上。
我的目标是创建它,使它拥有自己的.h和.cpp文件,如果我以后需要扩展它,只需添加一个新的成员函数来处理一些更模糊的错误操作类型。
我的问题是:
因为在error.h
我有代码:
class error_handler
{
// ctor dtor copy logger screen functions defined
}
在error_handler.cpp
中,我完成了这些定义,
我怎样才能简单地在课堂上添加新功能?我不希望对它进行分类,只需将其扩展即可。
对于用例场景,假设error_handler是在专有包中定义的类,我不能直接修改源代码,但允许在单独的代码中扩展它。
编辑:到目前为止,答案和评论似乎表明我正在尝试做一些语言不应该做的事情。如果是这样的话,我在这里学到了一些东西。希望事实并非如此,我会暂时搁置这个问题,看看还有什么可能会徘徊在这个帖子上......
答案 0 :(得分:2)
在C ++中,如果不修改class
块并添加函数定义(即在error.h
中),则无法修改类
如果您无法修改头文件,那么您唯一的选择是继承该类,或编写在该类上运行的非成员函数(但这些函数只能查看公共成员)
答案 1 :(得分:2)
这在很大程度上取决于这些功能是什么。鉴于您的应用程序,我将继续并假设您要添加的函数可用于处理其他错误类型。
为了保持简单,让我们假设每个函数(让我们称之为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);
答案 2 :(得分:1)
扩展类而不修改其原始定义的唯一方法是创建一个从中派生的新类。也许你应该对你想要做的更具体。使用error_handler
的现有代码是否必须受到更改的影响?例如,如果您只是想添加一个以不同方式记录错误的函数,并且只打算在新代码中使用该函数,那么可以创建一个普通的非成员函数接受引用error_handler
,但更简洁的方法是使用新方法创建my_error_handler
(派生)类。如果您希望将my_error_handler
实例传递给现有代码,则可以将error_handler
实例的指针/引用自由转换为指针/引用。