Я также должен отметить, что 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» в google, который должен дать вам несколько примеров, например. 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
.
Не пытайтесь реализовать код стиля C на C++ .. В C++ вы должны полагаться на исключения, чтобы сообщать об ошибке. Затем макросы обычно следует избегать в C++ - предпочитают обычные функции. –
Я хочу печатать переменные аргументы с форматированием без макросов, как это было в C, поэтому я прошу стиль в стиле C++. @MarinosK – hxpax
Итак, вы хотите использовать методы, которые вы используете на C, даже если на C++ существуют различные методы, которые обычно рекомендуются, поскольку они безопасны по типу (среди прочего) и считаются предпочтительными? – Peter