Модераторы: 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   Вверх
Страницы: (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.0617 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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