Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> variadic parameters to base class constructor, передача переодических параметров 
V
    Опции темы
InvalidProperty
Дата 29.1.2010, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



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

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

Идея:
Имеется базовый класс, конструктор которого принимает переменное число аргументов
Код

class A {
 public:
  A(const char *format, ...);
};

Имеется дочерний класс. Его конструктор также должен принимать переменное число аргументов и создавать базовый класс.

Постановка вопроса:
Как передать переменное число аргументов из конструктора дочернего класса в конструктор базового?

Размышления:
Чтобы произвести создание базового класса из конструктора дочернего с указанием некоторых параметров для конструктора базового класса, нужно написать примерно следующее:
Код

class A {
 public:
  A(int i);
};

class B : public A {
 public:
  B(int i) : A(i);          // создание базового класса с параметром
}

Но такая махинация для переменного числа параметров потерпит фиаско.

Решение:
В базовом классе создается статическая функция, которая будет отвечать за упаковку переменных параметров в строку:
Код

class A {
 private:
  char _str[MAXLINE];

 public:
  static char *pack(const char *format, ...);
  A(const char *str)
  {
   strcpy(_str, str);        // необходимо для того, чтобы не
   delete[] str;              // возникало утечек памяти
   printf("%s", _str);
  }
};

class B : public A {
 public:
  B(const char *str) : A(str) {}
};

int main()
{
 B b(A::pack("ok, it works fine %d times", 454));

 return 0;
}

и это будет работать!. Но! Как только мы попытаемся вызвать конструктор либо базового, либо дочернего класса, передавая строку, лежащую на стеке, или в статической памяти, приложение вылетит:
Код

B b("asfasdf");       // возникнет исключение, т.к. в конструкторе базового класса строка уничтожается

Для того, чтобы решить проблему, нужно создать некую структуру, которая будет содержать в себе строку, передаваемую конструкторам. Определение этой структуры ДОЛЖНО находиться в базовом классе, чтобы избежать создания такой структуры напрямую.

Полный код решения:
Код

#include <stdio.h>
#include <stdarg.h>
#include <string.h>


class A
{
public:
 char _str[453];
public:
 struct SS
 {
  char str[435];
 };

 static SS *pack(const char *format, ...)
 {
  SS        *sss = new SS;
  va_list    ap;

  va_start(ap, format);
  vsnprintf(sss->str, sizeof(sss->str), format, ap);
  va_end(ap);

  return sss;
 }

 A(SS *sss)
 {
  strcpy(_str, sss->str);
  delete sss;
  printf("constructor A\n");
  printf("A str = [%s]\n", _str);
 }
};

class B : public A
{
 public:
  B(SS *sss) : A(sss)
  {
   printf("constructor B\n");
   printf("B str = [%s]\n", _str);
  }
};

int main()
{
 B b(A::pack("asdfa %d", 5));
 SS s;                                            // эта строка вызовет ошибку компиляции, если ее убрать, программа будет работать отлично

 printf("%s\n", b._str);

 return 0;
}

Надеюсь, пояснений к коду не потребуется, но готов ответить на все вопросы smile

Это сообщение отредактировал(а) InvalidProperty - 29.1.2010, 17:39


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
InvalidProperty
Дата 29.1.2010, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



т.о. мы можем написать что-то вроде
Код

throw MyDerivedException(MyBaseException::pack("exception N %d", 45));

и получим именно то, что хотим


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
mes
Дата 29.1.2010, 17:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(InvalidProperty @  29.1.2010,  16:05 Найти цитируемый пост)
Надеюсь, пояснений к коду не потребуется, но готов ответить на все вопросы smile

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



--------------------
PM MAIL WWW   Вверх
zim22
Дата 29.1.2010, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(InvalidProperty @  29.1.2010,  16:05 Найти цитируемый пост)
Как передать переменное число аргументов из конструктора дочернего класса в конструктор базового?

вот так
Код

struct S {
  S(int x, ...) {}
};

struct Z : S {
  Z() : S(10, "yo", 22.33) { }
};



--------------------
PM MAIL   Вверх
InvalidProperty
Дата 29.1.2010, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



zim22, задача заключалась в передачи из конструктора дочернего класса именно тех же переменных параметров, что были переданы в него, а не просто каких-то

Добавлено через 59 секунд
mes, вторым постом я привел строку, которую можно использовать, применив данный метод

Добавлено через 2 минуты и 11 секунд
zim22, тем более, молодой человек, судя по коду, который Вы привели, Вы не прочитали пост вообще


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
zim22
Дата 29.1.2010, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(InvalidProperty @  29.1.2010,  16:56 Найти цитируемый пост)
 тем более, молодой человек, судя по коду, который Вы привели, Вы не прочитали пост вообще

я хоть свой возраст указал в инфо. 
насколько же вы молодой или старый - могу лишь догадываться.

но в одном я уверен на 100% - есть более изящный метод решения вашей теоретической проблемы.
***
и вообще, причём здесь возраст? smile 
"одни с годами умнеют - другие просто становятся старше."

Это сообщение отредактировал(а) zim22 - 29.1.2010, 18:10


--------------------
PM MAIL   Вверх
InvalidProperty
Дата 29.1.2010, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



Цитата(zim22 @  29.1.2010,  18:08 Найти цитируемый пост)
но в одном я уверен на 100% - есть более изящный метод решения вашей теоретической проблемы. 

так а я ведь всегда за здоровую критику. Давайте обсудим Ваш метод


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
zim22
Дата 29.1.2010, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



InvalidProperty, ок. напиши проблему, решение которой ты видишь только через использование ellipsis'a. 
я попробую решить её без них.


--------------------
PM MAIL   Вверх
InvalidProperty
Дата 29.1.2010, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



zim22, да что далеко ходить? Мне нужен класс исключений, который наследован от некоторого базового класса исключений. Нужно, чтобы и дочерний и базовый класс поддерживали конструкцию выбрасывания исключений с переменным числом параметров. Как Вы видите ее решение?

Код

throw DerivedException("some i parameter = %d, some j = %d, some string = %s", i, j, str);



--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
zim22
Дата 29.1.2010, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(InvalidProperty @  29.1.2010,  17:58 Найти цитируемый пост)
. Нужно, чтобы и дочерний и базовый класс поддерживали конструкцию выбрасывания исключений с переменным числом параметров

это не проблема. это деталь реализации.
***
примеры проблем:
1) есть картотека. для каждой из записей картотеки нужно применять разные алгоритмы анализа в зависимости от типа записи.
2) ...

Это сообщение отредактировал(а) zim22 - 29.1.2010, 19:03


--------------------
PM MAIL   Вверх
InvalidProperty
Дата 29.1.2010, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



zim22, Вы к чему это сказали? Вы вообще топик этот прочитали или просто пустились в философию? Топик посвящен конкретной теме. Если есть иное решение, то покажите, и мы его обсудим, а иначе получается, что Вы просто льете воду. Зачем топик засорять?


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
Леопольд
Дата 29.1.2010, 19:32 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



erased

И вообще, элипсис это рудимент доставшийся от С... smile

Это сообщение отредактировал(а) Леопольд - 29.1.2010, 19:44


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
NewDima
Дата 29.1.2010, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: нет
Всего: 12



а я извращенец  smile , воспринимайте, пожалуйста как шутку, ибо я решил просто сделать для семи параметров...
Код

#define PVOID(a) (reinterpret_cast<void*>(a))
#define DEFAULT_PARAMETERS_TYPES void* i1 = 0, void* i2 = 0, void* i3 = 0, void* i4 = 0, void* i5 = 0, void* i6 = 0, void* i7 = 0
#define DEFAULT_PARAMETERS_LIST i1, i2, i3, i4, i5, i6, i7
class Base_Exception {
protected:
    Base_Exception(char* format, DEFAULT_PARAMETERS_TYPES) {
        int k, a = 0;
        _asm {
            pusha
        }
        for (void **v = &i7; v >= &i1; v--) {
            if (!*v) continue;
            ++a;
            k = reinterpret_cast<int>(*v);
            _asm {
                push k;
            }
        }
        printf(format);
        while (a--) _asm {pop eax}
        _asm {
            popa
        }
    }
};
class Derived_Exception: public Base_Exception {
public:
    Derived_Exception(char* format, DEFAULT_PARAMETERS_TYPES):Base_Exception(format, DEFAULT_PARAMETERS_LIST) {
    }
};
...
Derived_Exception ex("%d %d %s", PVOID(1), PVOID(2), "ahhaha");

 smile 
PM ICQ   Вверх
zim22
Дата 29.1.2010, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(InvalidProperty @  29.1.2010,  18:12 Найти цитируемый пост)
Вы к чему это сказали?

проведу аналогию. уж люблю я их smile
Цитата

один молодой человек решил поехать за рубеж. взял он с собой кусок сала и 3 булки хлеба.
на таможне его остановили и велели предъявить паспорт: а он им и говорит:
паспорта у меня нету. он мне и не нужен. у меня есть кусок сала. хотите поделюсь?

мораль сей басни такова: не нужно решать задачу неправильными методами.
чтобы узнать какой метод правильный - нужно сначала понять саму задачу.


--------------------
PM MAIL   Вверх
andrew_121
Дата 29.1.2010, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 6
Всего: 33



Цитата(zim22 @ 29.1.2010,  19:48)
Цитата(InvalidProperty @  29.1.2010,  18:12 Найти цитируемый пост)
Вы к чему это сказали?

проведу аналогию. уж люблю я их smile
Цитата

один молодой человек решил поехать за рубеж. взял он с собой кусок сала и 3 булки хлеба.
на таможне его остановили и велели предъявить паспорт: а он им и говорит:
паспорта у меня нету. он мне и не нужен. у меня есть кусок сала. хотите поделюсь?

мораль сей басни такова: не нужно решать задачу неправильными методами.
чтобы узнать какой метод правильный - нужно сначала понять саму задачу.

философ епс smile 

ну расскажи что думаешь об этом. меня тоже такая задача посещает время от времени.


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
baldina
Дата 29.1.2010, 20:24 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



InvalidProperty, при помощи синтаксиса С++ данную проблему изящно не решить. ковыряясь только в конструкторах это невозможно.
Однако возник вопрос: что делает конструктор базового класса с переменным числом параметров, тип которых не проверяется в процессе компиляции? вероятно скармливает тому же vsnprintf. Тогда следующий вопрос - зачем классу исключений вообще этим заниматься? пусть конструирует строку тот, кто генерирует исключение, а класс исключения работает с постоянным числом параметров.  Всё, проблемы нет.
Обратите внимание: ваш pack() - совершенно инородный элемент в классе, класс нагружен не свойственным ему функционалом. Разделите функционал и проблема исчезнет.

PM MAIL   Вверх
zim22
Дата 29.1.2010, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(andrew_121 @  29.1.2010,  19:05 Найти цитируемый пост)
ну расскажи что думаешь об этом. меня тоже такая задача посещает время от времени.

вот самый простой вариант. чем не устраивает?
Код

#include "stdafx.h"
#include <iostream>

struct BaseExceptionClass {
  BaseExceptionClass(const char *message) : message_(message) { }
  const char *what() { return message_; }
private:
  const char *message_;
};

struct DerivedExceptionClass : BaseExceptionClass {
  DerivedExceptionClass(const char *message) 
    : BaseExceptionClass(message) { }
};

int _tmain(int argc, _TCHAR* argv[])
{
  const char *text = "superb";
  int number = 88;

  try {
    char buffer[256] = {0};
    sprintf(buffer, "hello, i am %s, %d", text, number);

    throw DerivedExceptionClass(buffer);

  } catch (DerivedExceptionClass &ex) {
    std::cout << ex.what();
  }
  return 0;
}




--------------------
PM MAIL   Вверх
baldina
Дата 29.1.2010, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



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

предваряя возможную дискуссию о разном числе неких разнотипных свойств, которые надо обрабатывать классу исключения, предложу в этом случае воспользоваться
std::vector <boost::variant> или std::vector <boost::any>.

Добавлено через 3 минуты и 7 секунд
Цитата(zim22 @  29.1.2010,  19:02 Найти цитируемый пост)
Цитата(InvalidProperty @  29.1.2010,  17:58 )
. Нужно, чтобы и дочерний и базовый класс поддерживали конструкцию выбрасывания исключений с переменным числом параметров

это не проблема. это деталь реализации.

 smile 
PM MAIL   Вверх
andrew_121
Дата 29.1.2010, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 6
Всего: 33



Цитата(baldina @  29.1.2010,  20:24 Найти цитируемый пост)
Однако возник вопрос: что делает конструктор базового класса с переменным числом параметров, тип которых не проверяется в процессе компиляции? вероятно скармливает тому же vsnprintf. Тогда следующий вопрос - зачем классу исключений вообще этим заниматься? пусть конструирует строку тот, кто генерирует исключение, а класс исключения работает с постоянным числом 

это верно. но наверняка не только мне и InvalidProperty хотелось бы получить такую возможность. и желательно не только строковое сообщение. было бы супер!
пример:
Код

int main() {
   try {
      std::ifstream file(name);
      if ( !file ) {
         throw exception_type("fname %s, error code%d", name, errno);
      }
   } catch(const exception_type& e) {
      std::cout << e.what() << std::endl;
      std::cout << e.func() << std::endl;
      std::cout << e.line() << std::endl;
      std::cout << e.ecode() << std::endl;
   }
   return 0;
}

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


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
baldina
Дата 29.1.2010, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



andrew_121, 

Цитата(baldina @  29.1.2010,  20:29 Найти цитируемый пост)
предваряя возможную дискуссию о разном числе неких разнотипных свойств, которые надо обрабатывать классу исключения, предложу в этом случае воспользоваться
std::vector <boost::variant> или std::vector <boost::any>.


PM MAIL   Вверх
andrew_121
Дата 29.1.2010, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 6
Всего: 33



baldina, по моему раньше этого не было. во всяком случае я этого не заметил.

еще думаю для этого подойдет boost.format


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
baldina
Дата 29.1.2010, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



andrew_121, кажется то, что выше, вы не читаете  smile 
PM MAIL   Вверх
andrew_121
Дата 29.1.2010, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 6
Всего: 33



Цитата(zim22 @  29.1.2010,  20:26 Найти цитируемый пост)
вот самый простой вариант. чем не устраивает?

этим -
Цитата(zim22 @  29.1.2010,  20:26 Найти цитируемый пост)
sprintf(buffer, "hello, i am %s, %d", text, number);




--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Lazin
Дата 29.1.2010, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



как-же мы любим придумывать несуществующие проблемы и решать их smile 
я, в свою очередь, хочу предложить такой способ решения проблемы передачи переменного числа параметров в конструктор базового класса
file: generate_ctor.ipp
Код

Derived(PARAMETER_DEFINITION_LIST) : Base(PARAMETER_LIST)
{
}
#undef PARAMETER_DEFINITION_LIST
#undef PARAMETER_LIST

other file:
Код

struct Base
{
    Base(int a) { std::cout << "1" << std::endl; }
    Base(int a, int b) { std::cout << "2" << std::endl; }
};

struct Derived : public Base
{
#define PARAMETER_DEFINITION_LIST int a
#define PARAMETER_LIST a
#include "generate_ctor.ipp"

#define PARAMETER_DEFINITION_LIST int a, int b
#define PARAMETER_LIST a, b
#include "generate_ctor.ipp"
};


Цитата(andrew_121 @  29.1.2010,  20:38 Найти цитируемый пост)
это верно. но наверняка не только мне и InvalidProperty хотелось бы получить такую возможность. и желательно не только строковое сообщение. было бы супер!

тогда тебе как-то придется генерировать класс с переменным числом членов и недетерминированым набором методов  smile 
PM MAIL Skype GTalk   Вверх
Lazin
Дата 29.1.2010, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(InvalidProperty @  29.1.2010,  17:40 Найти цитируемый пост)
Код

throw MyDerivedException(MyBaseException::pack("exception N %d", 45));

я не вижу смысла в этом, класс исключения - Copy Constructable, поэтому можно писать так:
Код

throw MyDerivedException(MyBaseException("exception N %d", 45));


 smile 

Это сообщение отредактировал(а) Lazin - 29.1.2010, 21:59
PM MAIL Skype GTalk   Вверх
mes
Дата 29.1.2010, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(InvalidProperty @  29.1.2010,  16:56 Найти цитируемый пост)
mes, вторым постом я привел строку, которую можно использовать, применив данный метод

тогда Вы неправильно поняли мое непонимание. Меня интересовала именно задача, а не неполучающийся способ ее реализовать.
Ну вообщем тут уже много ответили, но еще раз проакцентирую внимание:
Цитата(zim22 @  29.1.2010,  18:48 Найти цитируемый пост)
не нужно решать задачу неправильными методами.
чтобы узнать какой метод правильный - нужно сначала понять саму задачу. 

 smile 


--------------------
PM MAIL WWW   Вверх
InvalidProperty
Дата 30.1.2010, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



меня навели на мысль еще одного варианта решения, который, как мне кажется, является более изящным, чем первый:
Код

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#define MAXLINE        4096


class exFmt
{
 private:
  char _str[MAXLINE];

 public:
  const char *str()
   { return _str; }

  exFmt(const char *format, ...)
  {
   va_list    ap;
   va_start(ap, format);
   vsnprintf(_str, sizeof(_str), format, ap);
   va_end(ap);
  }

  exFmt(const exFmt &fmt)
   { memcpy(_str, fmt._str, sizeof(_str)); }

  exFmt() { }
};

class exBase
{
 private:
  exFmt        _fmt;

 public:
  const char *str()
   { return _fmt.str(); }

  exBase(const exFmt &fmt)
   { _fmt = fmt; }
};


class exDerived : public exBase
{
 public:
  exDerived(const exFmt &fmt) : exBase(fmt) { }
};


int main()
{
 try
 {
  throw exDerived(exFmt("the error occured in %d try-catch block", 1));
 }
 catch(exBase &ex)
 {
  printf("%s\n", ex.str());
 }

 return 0;
}



--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
Lazin
Дата 30.1.2010, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



этот вариант ни разу не изящный, обычный std::exception + boost.format - намного удобней, а главное обходятся без элипсиса smile 
PM MAIL Skype GTalk   Вверх
InvalidProperty
Дата 30.1.2010, 19:21 (ссылка)  | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: нет
Всего: 9



Lazin, удобство понятие относительное и сугубо индивидуальное. Не нужно излишних холиваров. Я, к примеру, недолюбливаю сторонние библиотеки, а строка форматирования printf для меня выглядит привычнее и удобнее.

Это сообщение отредактировал(а) InvalidProperty - 30.1.2010, 19:22


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
Lazin
Дата 30.1.2010, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(InvalidProperty @  30.1.2010,  19:21 Найти цитируемый пост)
Lazin, удобство понятие относительное и сугубо индивидуальное
согласен, но ведь еще существуют объективные признаки кода с "душком", в данном случае это оно и есть smile 
я лично не понимаю, зачем все это, если можно просто отформатировать строку и передать ее в конструктор класса исключения, еще я не понимаю, почему не используется std::exception, а используется свой велосипед
ну и на последок, если я захочу получить тот или иной параметр не в текстовом виде, что мне делать?

Цитата(InvalidProperty @  30.1.2010,  19:21 Найти цитируемый пост)
Я, к примеру, недолюбливаю сторонние библиотеки, а строка форматирования printf для меня выглядит привычнее и удобнее.

лично я бы не хотел работать в одной команде с вело-строителем любителем, потому-что вместо того, что-бы просто писать код, придется изучать аналоги уже хорошо известных вещей, вроде boost::format и std::exception
вот к примеру вариант с boost::exception
(не ручаюсь за правильность, пишу по памяти)
Код

typedef boost::error_info<struct tag_line_number, std::string> LineNumberErrInfo;
typedef boost::error_info<struct tag_file_name, std::string> FileNameErrInfo;

class SpecificError : public boost::exception, public std::exception
{
};

....

try
{
...
   throw SpecificError() << LineNumberErrInfo(_LINE_) << FileNameErrInfo(__FILE__);
}
catch(SpecificError& e)
{
    std::cout << boost::diagnostics_information(e) << std::endl;
    std::cout << "Line: " << boost::get_error_info<LineNumberErrInfo>(e) << std::endl;
    ...
}

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

Это сообщение отредактировал(а) Lazin - 30.1.2010, 20:01
PM MAIL Skype GTalk   Вверх
andrew_121
Дата 31.1.2010, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 6
Всего: 33





--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
BEOWOLF
Дата 1.2.2010, 02:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 24.8.2007

Репутация: нет
Всего: 2



Цитата

Но! Как только мы попытаемся вызвать конструктор либо базового, либо дочернего класса, передавая строку, лежащую на стеке, или в статической памяти, приложение вылетит:
а почему вдруг приложение должно вылететь? Ну если строка в стеке удалена к моменту выполнения конструктора - то конечно вылетит, ну а в статической памяти - только если её вручную удалить.

А вообще подобного рода проблема решается другим, изящным способом - через использование объектов, содержащих свой конструктор/деструктор. То есть, вместо передачи const char* в качестве параметра, лучше передать const std::string&, в этом случае код всегда адекватно выполнится. Ну а если нужно передать форматированную строку, то пишите вот такую вот функцию:
Код

inline std::string __cdecl format(LPCSTR lpszFormat, ...)
{
    va_list argList;
    va_start(argList, lpszFormat);

    size_t bsz = _vscprintf(lpszFormat, argList);
    std::string res((std::string::size_type)bsz, 0);
    vsprintf_s((LPSTR)res.data(), bsz+1, lpszFormat, argList);

    return res;
};
и дальше в конструкторе можно написать вызов типа A(format("1param = %u, 2param = %u", i, j));
Кроме того, незабываем использовать auto_ptr, если всё-таки есть работа с выделенными объектами и выброс исключений, а ещё лучше умные указатели smile
PM MAIL   Вверх
xvr
Дата 1.2.2010, 15:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



В таком случае я обычно делаю немного по другому:
Код

class BaseEx {
public:
 BaseEx();

 void init(const char*, va_list);
};

class DerivedEx : public BaseEx {
public:
 DerivedEx(const char* msg, ...)
  {
   va_list p;
   va_start(msg,p);
   init(msg,p);
   va_end(p);
  }
};



PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0950 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.