Russian Qt Forum
Май 17, 2024, 19:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Конструктор и лог  (Прочитано 9896 раз)
AzazelloAV
Гость
« : Сентябрь 12, 2015, 22:45 »

Хочу выстрелить в ногу и никак не получается, хотя вроде с++.

Задача - просто при создании объекта выводить  - Enter to class %nameOfClass. (Чтобы не было дурных вопросов, это парсинг файла, нужно для дебага). Ну нету решений, нету не то что красивых решений, нету тупо никаких.

1 вариант - самый плохой. Использовать TypeInfo (пусть в нашем случае QObject). Отбросим оверхед. Так для каждого класса поди используй Q_OBJECT. Промахнулся(забыл написать или ещё чего) и теперь ищи что глючит - то ли твой основной код, то ли код, который дебаг пишет. На тестовый код ещё тестовый код писать.
2 вариант - тупо в каждом конструкторе писать логирование. Не вижу отличие от 1-го варианта.
3 теоретический вариант (невозможен, зато идеален) - чисто виртуальная функция с именем класса. При создании класса компилятор тебя пошлет подальше, если её не определил. Но, как известно, виртуальная функция в конструкторе не вызывается (вызываются при определённых условиях, они нам не подходят).

Итог. Получается вот что - пишешь описание класса, и каким то образом говоришь (даже себе через некоторое время) - читай описание! И при использование класса то там нужно подковырнуть, то там нужно подковырнуть.

Может я в стену упёрлся и не вижу простого решения?
А теперь собственно вопрос.

Как выводить информацию из конструктора для определённого класса и при этом!!!!! знать, что ты не забыл определить эту информацию.
« Последнее редактирование: Сентябрь 12, 2015, 22:49 от AzazelloAV » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #1 : Сентябрь 12, 2015, 23:24 »

Надуманная проблема. К тому же едва ли поможет при отладке..

Но как вариант:
Код
C++ (Qt)
template <class T>
struct base
{
   base() { std::clog << "Enter to class " << typeid(T).name() << std::endl; }
};
 
struct myclass : public base<myclass>
{
...
};
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
AzazelloAV
Гость
« Ответ #2 : Сентябрь 12, 2015, 23:41 »

Надуманная проблема. К тому же едва ли поможет при отладке..

Но как вариант:
Код
C++ (Qt)
template <class T>
struct base
{
   base() { std::clog << "Enter to class " << typeid(T).name() << std::endl; }
};
 
struct myclass : public base<myclass>
{
...
};
 


Надуманная проблема?
Гм. Нет слов. В чем её надуманость.

Вы представте себе код, основной. И код, который ещё перегружен #ifdef для юнит тестов. В чём для вас надумманость?
Ну как вам сказать. Ну вот собрались куча гуру, мол взламать пароль к серверу пентагона.
А тут кто-то вскакиват и говорит - будем использовать перебор паролей!
« Последнее редактирование: Сентябрь 12, 2015, 23:43 от AzazelloAV » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #3 : Сентябрь 12, 2015, 23:55 »

Цитировать
Гм. Нет слов. В чем её надуманость.

Цитировать
Как выводить информацию из конструктора для определённого класса и при этом!!!!! знать, что ты не забыл определить эту информацию.

Во-вторых,
Цитировать
Ну вот собрались куча гуру, мол взламать пароль к серверу пентагона.
А тут кто-то вскакиват и говорит - будем использовать перебор паролей!
знаете, думаю для гуру тратить своё время на форуме, задавая подобные вопросы (Как выводить информацию из конструктора для определённого класса) - это последнее, что пришло бы им в голову  Улыбающийся

Не, я, конечно, за всех гуру не отвечаю, это просто моё имхо)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
AzazelloAV
Гость
« Ответ #4 : Сентябрь 13, 2015, 00:21 »


Не, я, конечно, за всех гуру не отвечаю, это просто моё имхо)

Тогда зачем вы потратили свое время на данный опус?
Вы видно задачу не поняли, поэтому сводите всё к тому, что это возможно. Я же вам говорил совершенно про другое - про "не напряжно".
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #5 : Сентябрь 13, 2015, 00:33 »

Цитировать
Тогда зачем вы потратили свое время на данный опус?
Ну так я же не говорю, что я гуру) И потом кто из нас эту тему начал?)

Цитировать
Я же вам говорил совершенно про другое - про "не напряжно".
Что для вас "не напряжно"?
Я так понимаю, вставить одну строчку в конструктор
Код
C++ (Qt)
struct myclass
{
   myclass()
  {
      LOG(myclass) // обычный макрос
      ...
  }
};
 
это напряжно? А вдруг забудем?)

Чтож дальше будет?  Улыбающийся



Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Bepec
Гость
« Ответ #6 : Сентябрь 13, 2015, 00:50 »

Красивого решения нет.
И вам предложили все простые варианты Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Сентябрь 13, 2015, 07:06 »

Как выводить информацию из конструктора для определённого класса и при этом!!!!! знать, что ты не забыл определить эту информацию.
Выводить - макрушник в духе Q_OBJECT. "Не забыть" - придется лепить что-то типа RegisterClass, который отсыпет ошибку компиляции если нет макрушника. Ну и на старте
Код
C++ (Qt)
RegisterClass<MyClass1>();
RegisterClass<MyClass2>();
...
RegisterClass<MyClass888>();
Записан
AzazelloAV
Гость
« Ответ #8 : Сентябрь 13, 2015, 11:37 »

Спасибо за предоставленные решения. Значит буду в "лоб" писать и исчезнет чувство, что может быть по другому.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Сентябрь 13, 2015, 13:06 »

Цитировать
Я же вам говорил совершенно про другое - про "не напряжно".
Что для вас "не напряжно"?
Я так понимаю, вставить одну строчку в конструктор
Код
C++ (Qt)
struct myclass
{
   myclass()
  {
      LOG(myclass) // обычный макрос
      ...
  }
};
 
это напряжно? А вдруг забудем?)

Чтож дальше будет?  Улыбающийся
Легковесный подход - "невставка" ничем не грозит, а надо чтобы отливалась в ошибки компиляции. Да и конструкторов может быть не один, или вообще не быть. А еще конструкторы копирования и перемещения. И уже с десятком классов забот хватает.

Конечно невозможно запретить написать класс "без этого", таких средств нет в языке.  Но лучше как-то так
Код
C++ (Qt)
struct myclass {
MyAgent<myclass> agent;  // завернуть в макруху
 
Код
C++ (Qt)
template <class T>
struct MyAgent {
 MyAgent ( void )
 {
   std::clog << "Enter to class " << typeid(T).name() << std::endl;  
 }
 ...
 
Впрочем это уже по Вашей части  Улыбающийся
Записан
AzazelloAV
Гость
« Ответ #10 : Сентябрь 13, 2015, 13:45 »


Легковесный подход - "невставка" ничем не грозит, а надо чтобы отливалась в ошибки компиляции. Да и конструкторов может быть не один, или вообще не быть. А еще конструкторы копирования и перемещения. И уже с десятком классов забот хватает.

Конечно невозможно запретить написать класс "без этого", таких средств нет в языке.  Но лучше как-то так
Код
C++ (Qt)
struct myclass {
MyAgent<myclass> agent;  // завернуть в макруху
 
Код
C++ (Qt)
template <class T>
struct MyAgent {
 MyAgent ( void )
 {
   std::clog << "Enter to class " << typeid(T).name() << std::endl;  
 }
 ...
 
Впрочем это уже по Вашей части  Улыбающийся

Слишком, слишком сложно.
Ведь это не основной код, вспомогательный.
Тут ещё вылазит проблема иерархии классов. Классов много, действительно, они просты и примитивны, но, в тоже время есть промежуточные, которые во всей иерархии напрямую не вызываются (наследуются).

Тут ведь в чем вопрос. В основном коде (если так можно выразиться) мы может контроллировать ситуацию и применять какие то правила. Юнит тестами мы выравнимаем ситуацию, если что-то пропустили. Но контролировать её ещё и в дополнительном коде (который использует юнит тест)..... Так на юнит тест я ещё буду писать юнит тест.

Сама задача не важна, но приведу вам пример, чтобы поняли глубину, так сказать.
Парсинг С++ файла. Не компиляция, а просто синтаксический разбор.
И вот вы находите if, создаётся класс, который отвечает за парсинг if.... Вообщем классическая нисходящая рекурсия. Т.е. классов много. И жизнь у них очень мала.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #11 : Сентябрь 13, 2015, 14:03 »

Цитировать
Да и конструкторов может быть не один, или вообще не быть. А еще конструкторы копирования и перемещения. И уже с десятком классов забот хватает.
Ну да, согласен..

Цитировать
Впрочем это уже по Вашей части  Улыбающийся
Тогда уж можно и без всяких шаблонов:
Код
C++ (Qt)
#ifdef DEBUG
#define LOG(T) struct logger_##T \
{ logger_##T() { std::clog << "Enter to class " << #T << std::endl; } }; \
   logger_##T _logger_##T;
#else
#define LOG(T)
#endif
 
class myclass
{
   LOG(myclass)
};
 
 
int main()
{
   myclass myobject;
}
 

Цитировать
Тут ещё вылазит проблема иерархии классов. Классов много, действительно, они просты и примитивны, но, в тоже время есть промежуточные, которые во всей иерархии напрямую не вызываются (наследуются).
Не, сейчас о наследовании речи не идёт. Макрос "инстанцирует" в ваш класс этакого логгера, который при конструировании будет делать, что вы ему скажете..

Цитировать
И вот вы находите if, создаётся класс, который отвечает за парсинг if.... Вообщем классическая нисходящая рекурсия. Т.е. классов много. И жизнь у них очень мала.
С этого момента лучше поподробнее)
« Последнее редактирование: Сентябрь 13, 2015, 14:11 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
AzazelloAV
Гость
« Ответ #12 : Сентябрь 13, 2015, 14:28 »


Не, сейчас о наследовании речи не идёт. Макрос "инстанцирует" в ваш класс этакого логгера, который при конструировании будет делать, что вы ему скажете..
Агаг. Проблема начинает вылазить, когда нам нужно решать, в какой класс записывать лог, в какой нет.
Т.е. именно проблема в наследовании и проявляется. При создании класса (далее я под созданием класса имею в виду создание объекта класса) выводить нам нужно имя базового класса? Нет конечно. А если базовый класс не промежуточный и тоже может участвовать в работе?
Вывод содержимого "Enter to class Name1" и сразу "Enter to class Name2" что означает? Что мы вызвали базовый класс или класс запустил новый? Если уж по аналогии с if - то он может запустить класс ParseBoolCondition, либо наследоваться от фиг значет чего. А вывод всегда один и тот же. Я надеюсь внятно описал, т.к. очень запутано изъясняюсь.

И вот вы находите if, создаётся класс, который отвечает за парсинг if.... Вообщем классическая нисходящая рекурсия. Т.е. классов много. И жизнь у них очень мала.
Цитировать
С этого момента лучше поподробнее)

Ну, это не та задача, которую следует в данном топике обсуждать. Я её для примера привёл.
Я так понимаю, тема вам интересна, но обсуждение её заведёт в дебри.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #13 : Сентябрь 13, 2015, 14:46 »

Цитировать
Агаг. Проблема начинает вылазить, когда нам нужно решать, в какой класс записывать лог, в какой нет.
Т.е. именно проблема в наследовании и проявляется. При создании класса (далее я под созданием класса имею в виду создание объекта класса) выводить нам нужно имя базового класса? Нет конечно. А если базовый класс не промежуточный и тоже может участвовать в работе?
Вывод содержимого "Enter to class Name1" и сразу "Enter to class Name2" что означает? Что мы вызвали базовый класс или класс запустил новый?
Ну это тож решается.. Если я правильно понял, то вы хотите как то так:
Код
C++ (Qt)
class base
{
   LOG(base)
};
 
class derived : public base
{
   LOG(derived)
   REMOVE_LOG(base)
};
 
Это в принципе можно сделать..

Цитировать
Я так понимаю, тема вам интересна, но обсуждение её заведёт в дебри.
Ну как бы это сказать.. Не то чтобы интересна, просто меня всегда настораживают конструкции if-else-switch в коде, которые превращают его в спагетти код.. Возможно, есть решение более изящьнее.. Но да, это заведёт нас в дебри околоархитектурных вопросов и рукомаханий, которые здесь не особо любят)
Собственно, я по этому и спросил)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
AzazelloAV
Гость
« Ответ #14 : Сентябрь 13, 2015, 14:52 »

Ну это тож решается.. Если я правильно понял, то вы хотите как то так:
Код
C++ (Qt)
class base
{
   LOG(base)
};
 
class derived : public base
{
   LOG(derived)
   REMOVE_LOG(base)
};
 
Это в принципе можно сделать..
 

Это опять же усложнение, проще придерживаться правил. Тем более, REMOVE_LOG(base) - мыслей нет, что там может быть.
Не важно, не говорите, что там можно реализовать, это не имеет значение, т.к. усложняет всё.

Цитировать
Ну как бы это сказать.. Не то чтобы интересна, просто меня всегда настораживают конструкции if-else-switch в коде, которые превращают его в спагетти код.. Возможно, есть решение более изящьнее.. Но да, это заведёт нас в дебри околоархитектурных вопросов и рукомаханий, которые здесь не особо любят)
Собственно, я по этому и спросил)

При чём здесь спагетти в коде при парсинге кода? Нам дано, что дано и все варианты нужно отработать. Тем более, я не парсю с++, я парсю MIB, приводил для примера.

Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.282 секунд. Запросов: 22.