我想覆盖 std 函数的行为,比如 std::time。是否可以调用 std::time 并通过我的自定义函数进行路由?
5 回答
std
一般来说,命名空间是不受限制的。向命名空间添加新函数、重载、类或其他任何东西std
都是**未定义的行为*。
唯一的例外是模板特化。您可以在std
命名空间中提供函数的特化。经常执行此操作的功能是std::swap
.
这听起来是个非常糟糕的主意。有点像重新定义true
or false
。更好的方法是编写自己的包装函数,比如tim_time()
,它可能会或可能不会在std::time()
内部调用。
不要调用它std::time
,而是路由您有时可能会通过不同的命名空间覆盖的所有调用。
namespace mystd{
using namespace std;
void time() { ... }
}
// ...
mystd::time(); // not std::time
mystd::copy(...); // calls std::copy, unless you override it like time()
然后调用mystd::time
将调用该函数的修改版本。如果您调用非覆盖函数,例如,mystd::copy
它将正确解析为原始 std 函数。
不便携。根据标准没有定义会发生什么的理解,您通常可以在命名空间 std 中定义您喜欢的任何符号和函数,或者链接到定义这些符号的库,或其他任何东西。这只是未定义的行为。所以你所能做的就是把它吸进去看看,并希望它不会在你的编译器的下一个版本中出现问题。
也就是说,对于大多数编译器,它可能大部分都可以工作,前提是您避免与“真正的”std::time 发生单一定义规则冲突。这是因为大多数编译器实际上并没有对命名空间 std 做任何特殊的事情,而且他们用来实现它的头文件和库与您可以自己编写的头文件和库没有任何不同。
不过,Dima 是绝对正确的,像这样脱离标准几乎总是一个非常糟糕的主意。也许如果你被困在一些调试地狱中,你基本上想将日志记录添加到 std::time,但不能,那么值得考虑。否则不要去那里。如果你想测试一些代码,看看它是否在不同的时间正常工作,然后给那个代码传递一个参数(或模板参数),指定它应该调用哪个时间函数。
在某些平台上,您可以完成此操作。在您的源代码中,定义函数,即
extern "C" time_t time(time_t *value)
{
...
}
如果幸运的话,链接器将比std::time
标准库中的版本更紧密地绑定您的版本。当然,不能保证这会起作用,或者以您想要的方式链接。不利的一面是,您不再可以访问原始std::time
.
正如其他人所发布的那样,这不是可移植的行为。我很确定它可以在 Linux 上运行。我也相当肯定它在 Windows 上不起作用(链接器抱怨冲突)。