Идентификатор экземпляра класса ведения журнала C ++ - PullRequest
0 голосов
/ 24 мая 2018

В моем проекте некоторые классы создаются более одного раза.Каждый класс регистрирует некоторые события.Метод ведения журнала является общим для всего проекта и использует стандарт cout .Сообщение журнала содержит время, имя класса, имя метода, значение переменной и пользовательское сообщение.

Недостатком является то, что журнал не привязан к конкретному экземпляру.Я не знаю, какой экземпляр класса написал журнал.

Есть ли хороший способ решить эту проблему без добавления дополнительных статических членов в качестве счетчиков экземпляров в классы?Я использую boost и C ++ 11.Возможно, в boost есть что-то, что может помочь.

Единственное решение, о котором я могу подумать, - это включить в экземпляр адрес (этот) в журнал.

Ответы [ 5 ]

0 голосов
/ 24 мая 2018

Вы можете легко генерировать идентификаторы с помощью адаптера CRTP, как этот (если вы можете немного изменить свои классы)

template<typename T>
struct enable_id
{
    int id = global_id++;
private:
    static int global_id;
};

template<typename T>
int enable_id<T>::global_id = 0;

class foo : public enable_id<foo>
{
};

template<typename T>
void log(const T& t)
{
    // if is_base_of
    std::cout << t.id << std::endl;
}
0 голосов
/ 24 мая 2018

Если будет только несколько экземпляров класса, я бы предложил вам ввести строковый член и инициализировать его уникальным именем во время создания объекта.Это поможет вам в чтении журналов.По умолчанию он может быть инициализирован с адресом объекта.

0 голосов
/ 24 мая 2018

У меня обычно есть защищенный член класса, содержащий время создания экземпляра в корне всех моих иерархий классов, по крайней мере, на этапе отладки.Также очень полезно для многопоточных приложений.

Преобразуйте это время во все, что вы хотите - строку, миллисекунды, время эпохи - и у вас будет уникальный идентификатор для каждого экземпляра.

0 голосов
/ 24 мая 2018

Вам нужно будет различать разные классы где-то , вот несколько вариантов (все полагаются на какой-то идентификатор):

  1. Добавьте некоторую дополнительную статическую переменную.Не вариант для вас, но, на мой взгляд, лучший путь, если вы стремитесь к читабельности.
  2. Используйте this, как вы предложили:Это, очевидно, генерирует уникальные идентификаторы, но они, как правило, будут нечитаемыми, и их будет трудно различить при растущей длине адреса (так как только один или два символа могут отличаться в длинной адресной строке).Кроме того, адреса могут меняться при каждом запуске приложения (особенно при использовании ASLR), поэтому вы не сможете увидеть, какой именно экземпляр создал какую строку вывода (если это требуется).
  3. Используйте this и хэшируйте значение :

Если честно, я не вижу большой разницы в 2), но это может вызвать некоторые дальнейшие идеи.Некоторый уродливый хак может выглядеть так:

#include <iostream>
#include <functional>
#include <cstddef>

class Logger
{
public:
    static void log(void* ptr)
    {
        using hash_type = std::uintptr_t;
        std::cout << std::hash<hash_type>{}(reinterpret_cast<hash_type>(ptr))
            << " logged something..." << std::endl;
    }
};

Вы также можете рассмотреть , специализирующую std::hash для ваших классов, и использовать это в выходных данных журнала.Это устранит проблему смены адресов между различными запусками, если все будет реализовано правильно.

Создание идентификатора во время построения (например, путем передачи некоторого идентификатора в конструктор):На самом деле это не вариант, поскольку у вас нет никаких доказательств или контроля, что для каждого класса генерируется уникальный идентификатор - если только вы не используете какую-то (абстрактную) фабрику с доступом к частному конструктору или какой-то глобальный реестр (см. Ниже). Используйте некоторую вспомогательную утилиту, где ваши классы журналирования регистрируются и генерируются уникальные идентификаторы (что-то вроде класса регистрации).Для простых целей регистрации, ИМХО, это раздувание и не добавляет никакого значения по сравнению с 1).

Вывод: Я бы выбрал вариант 1), если читаемость для людей имеетбеспокойство и для 2), если вы просто хотите, чтобы какое-то число различало сообщения журнала (например, для трубопроводов и фильтрации).

0 голосов
/ 24 мая 2018

Самый простой способ исправить проблему - напечатать адрес, чтобы указать, какой это объект.Как показано ниже:

cout<<static_cast<void*>(this)<<endl;

Или вывести некоторые функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...