我还必须指出,C++ 和 C 是两种不同的语言,具有不同的模式和习语。 C++ 为许多 C 结构提供了更好的替代方案,这些结构更安全,因此更可取。在你的情况下,我会在这种情况下抛出一个异常。如果您在代码中禁止catch(...),它将终止您的程序。当传播异常时,编译器还将调用对象的析构函数,从而进行清理。如果您还没有,我建议您阅读资源获取即初始化 (RAII)。因为看起来您正在从 C 过渡到 C++,所以我建议阅读 the tour of C++,它展示了基本的 C++ 原则。对于 RAII,其要点是管理特殊处理程序对象中的资源,这些处理程序对象在构造函数中分配,在析构函数中释放,并实现移动语义。这样,您就不会泄漏资源。示例实现是std::vector、std::unique_ptr 或std::iostream。再举一个例子,考虑互斥锁/解锁:
class Mutex {
public:
void lock() { ... }
void unlock() { ... }
};
使用它时,很容易忘记在代码中解锁,尤其是在修改现有代码时。此外,如果出现异常,您需要 try/catch 块来一直解锁。相反,定义一个MutexLocker 类:
class MutexLocker
{
public:
MutexLocker(std::mullptr_t) = delete;
MutexLocker(Mutex* m): mutex_(m) {mutex_->lock();}
MutexLocker(MutexLocker const&) = delete;
MutexLocker& operator=(MutexLocker const&) = delete;
MutexLocker(MutexLocker&& l): mutex_(l.mutex_) {l.mutex_ = nullptr;}
MutexLocker& operator=(MutexLocker&& l)
{
mutex_ = l.mutex_,
l.mutex_ = nullptr;
return *this;
}
~MutexLocker() {if (mutex_) {mutex_->unlock()} };
private:
Mutex* mutex_;
};
现在,您永远不会忘记解锁互斥锁。 MutexLocker 对象无法复制,但您可以转让所有权。这比你在 C 中可以做的任何事情都要好。
对于格式化输出,你可以谷歌“variadic template printf”,它应该会给你一些例子,例如on Wikipedia:
void printf(const char *s)
{
while (*s) {
if (*s == '%') {
if (*(s + 1) == '%') {
++s;
}
else {
throw std::runtime_error("invalid format string: missing arguments");
}
}
std::cout << *s++;
}
}
template<typename T, typename... Args>
void printf(const char *s, T value, Args... args)
{
while (*s) {
if (*s == '%') {
if (*(s + 1) == '%') {
++s;
}
else {
std::cout << value;
s += 2; // this only works on 2 characters format strings ( %d, %f, etc ). Fails miserably with %5.4f
printf(s, args...); // call even when *s == 0 to detect extra arguments
return;
}
}
std::cout << *s++;
}
}
或者您可以使用库,例如boost::format 或可能有数千个其他实现。如果仅用于日志记录,您可以查看日志记录框架,例如boost.log.