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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Неразобрался с наследованем, как/в каком порядке вызывать кнструкторы 
V
    Опции темы
Programister0
Дата 4.6.2007, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



допустим есть шаблон класса
Код

template <class TYPE>
class s0
{
  private:
        TYPE   *v;
        DWORD   n;           

  public:
      s0(){v=new TYPE[10];};
      s0(const s0    &s)
        {
          n=s.n;
          v=new TYPE[n+1];
          memcpy(v,s.v,n);
        };
     ~s0()
        {
          delete [] v;
        }; 
};


и есть два предка от этого класса
первый:
Код

template <class TYPE>
class s0_1: public s0<TYPE>
{
  private:
        TYPE     *v1;          
  public:
      s0_1():s0<TYPE>()                //сначала вызываем конструктор для переменных s0
        {
          v1=new TYPE[10];            //затем пишем свой для s0_1
        };
      s0_1(const s0_1    &s):s0<TYPE>(s)
        {
          v1=new TYPE[n+1];
          memcpy(v1,s.v1,n);
        };
     ~s0_1()
        {
          delete [] v1;                   //здесь освобождаем только для v1 
                                                //т.к. после ~s0_1() деструктор  для ~s0()  
                                                //вызывается автоматически
        };  
};


втрой:
Код

template <class TYPE>
class s0_2: public s0<TYPE>   //практически тоже самое что и s0_1
{
  private:
        TYPE     *v2;
        DWORD   n2;                    //за исключением  вот этого     
  public:
      s0_2():s0<TYPE>()        
        {
          v2=new TYPE[10];          
        };
      s0_2(const s0_2    &s):s0<TYPE>(s)
        {
          n2=n;
          v2=new TYPE[n2+1];
          memcpy(v2,s.v2,n2);
        };
     ~s0_2()
        {
          delete [] v2; 
        };  
};


а вот и вопрос:
надо создать класс включающий в себя всё из предыдущих 3-х классов
Код

template <class TYPE>
class s1: public s0_1<TYPE>,public s0_2<TYPE> 
//нужно ли писать public s0<TYPE> или это и так понятно компилятору
{

  public:
      s1():???                 //какие конструкторы здесь 
        {                      //вызывать чтобы все работало корректно            
        };
      s1(const s1   &s)::???
        {
        };
     ~s1(){};                 //нужен ли деструктор в этом классе если 
                              // нет никаких динамич-х переменных
};

вообще возможно ли как нибудь 
попроще написать чтото подобное?




PM MAIL WWW ICQ Skype   Вверх
nickless
Дата 4.6.2007, 19:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


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

Репутация: 19
Всего: 181



Чтобы можно было использовать аттрибуты класса в потомках (например n в s0_1), они должны быть в секции protected.

Цитата(Programister0 @  4.6.2007,  13:24 Найти цитируемый пост)
и есть два предка от этого класса

Для s0 это потомки, предки они только для s1

Цитата(Programister0 @  4.6.2007,  13:24 Найти цитируемый пост)
class s0_1: public s0<TYPE>
...
          v1=new TYPE[n+1];

Тут надо написать s0<TYPE>::n (это ИМХО изза шаблонов). В s0_2 к стати n тоже пару раз используется.

Цитата(Programister0 @  4.6.2007,  13:24 Найти цитируемый пост)
нужно ли писать public s0<TYPE> или это и так понятно компилятору

Не напишешь - будет protected

Цитата(Programister0 @  4.6.2007,  13:24 Найти цитируемый пост)
какие конструкторы здесь вызывать

s0_1<TYPE>() и s0_2<TYPE>() - т.е. всех классов, от которых наследуем.
Заметь, что в этом случае, s1 будет иметь 2 копии всех аттрибутов и методов класса s0, и нужно будет явно указывать, через какой класс (s0_1 или s0_2) ты к ним хочешь обратится.
Т.е. например s0_1<TYPE>::n и s0_2<TYPE>::n - это разные переменные.

Цитата(Programister0 @  4.6.2007,  13:24 Найти цитируемый пост)
нужен ли деструктор в этом классе

Нет.

Цитата(Programister0 @  4.6.2007,  13:24 Найти цитируемый пост)
вообще возможно ли как нибудь попроще написать чтото подобное?

Смотря что нужно, если обязательно множественное наследование и шаблоны - сомневаюсь  smile 


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
Rockie
Дата 4.6.2007, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 8
Всего: 31



Цитата

 public:
      s1():???                 //какие конструкторы здесь 
        {                          //вызывать чтобы все работало корректно    

Programister0, вроде бы imho никакие.. У базовых классов есть конструкторы по умолчанию, поэтому явно вызывать конструкторы предков нет необходимости.
Цитата

     ~s1(){};           //нужен ли деструктор в этом классе если 
                              // нет никаких динамич-х переменных

imho в С++ вообще нужны деструкторы. Если ты не объявишь его, компилятор сам его сгенерирует.




--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
Programister0
Дата 4.6.2007, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

и есть два предка от этого класса

оговорился т.е. опечатался?

Цитата

class s0_1: public s0<TYPE>
...
          v1=new TYPE[n+1];
Тут надо написать s0<TYPE>::n (это ИМХО изза шаблонов). В s0_2 к стати n тоже пару раз используется.

пнятно 
я писал это в Builder'е он вроде понял, но возьму на заметку

Код

template <class TYPE>
class s1: public s0_1<TYPE>,public s0_2<TYPE>
[quote]
s0 Не напишешь - будет protected
[/quote]
//т.е. все функции и св-ва s0 которые копируются 2-раза будут доступны только внутри этого класса
{
  public:
      s1():s0_1<TYPE>():s0_2<TYPE>()
[quote]
s0_1<TYPE>() и s0_2<TYPE>() - т.е. всех классов, от которых наследуем.
[/quote]
        {
        };
      s1(const s1   &s):s0_1<TYPE>(s):s0_2<TYPE>(s)
        {
        };
     ~s1(){};

};

вот в этом и пробема 
размер 
s0=8,
s0_1=12 =s0+s0_1
s0_2=16 =s0+s0_2
s1=28     =s0+s0+s0_1+s0_2

как обьяснить компилятору что s0 нужна только в 1-м экземпляре в s1
если её(s0) функции не переопределяются в s0_1 и s0_2.

благодарю за разьснение;


PM MAIL WWW ICQ Skype   Вверх
nickless
Дата 4.6.2007, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


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

Репутация: 19
Всего: 181



Цитата(Programister0 @  4.6.2007,  22:20 Найти цитируемый пост)
как обьяснить компилятору что s0 нужна только в 1-м экземпляре в s1

Используй виртуальное наследование, т.е. 
Код

class s0_1: virtual public s0<TYPE>
и
class s0_2: virtual public s0<TYPE>

Читай про это например тут


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
Damarus
Дата 5.6.2007, 07:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 671
Регистрация: 6.5.2006

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



Цитата(Rockie @  4.6.2007,  20:15 Найти цитируемый пост)
imho в С++ вообще нужны деструкторы. Если ты не объявишь его, компилятор сам его сгенерирует.


Rockie, ты это загнул  smile 
PM MAIL ICQ Jabber   Вверх
Rockie
Дата 5.6.2007, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 8
Всего: 31



Damarus, хе)) Ну так оно и есть smile default destructor





--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
Damarus
Дата 5.6.2007, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 671
Регистрация: 6.5.2006

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



default destructor - это конечно да, только я про первую часть smile 
PM MAIL ICQ Jabber   Вверх
Rockie
Дата 5.6.2007, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 8
Всего: 31



Damarus, а, это мы легко  smile 





--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
Programister0
Дата 5.6.2007, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Код

template <class TYPE>
class s0
{
  protected:
        TYPE   *v;
        DWORD   n;           
  public:
      s0(){v=new TYPE[10];};
      s0(const s0    &s)
        {
          n=s.n;
          v=new TYPE[n+1];
          memcpy(v,s.v,n);
        };
     ~s0()
        {
          delete [] v;
        }; 
};

template <class TYPE>
class s0_1: public virtual s0<TYPE>  //virtual
{
  protected:
        TYPE     *v1;          
  public:
      s0_1():s0<TYPE>()
        {
          v1=new TYPE[10];
        };
      s0_1(const s0_1    &s):s0<TYPE>(s)
        {
          v1=new TYPE[n+1];
          memcpy(v1,s.v1,n);
        };
     ~s0_1()
        {
          delete [] v1;


        };  
};

template <class TYPE>
class s0_2: public virtual  s0<TYPE>   //virtual
{
  protected:
        TYPE   *v2;
        DWORD   n2;
  public:
      s0_2():s0<TYPE>()        
        {
          v2=new TYPE[10];          
        };
      s0_2(const s0_2    &s):s0<TYPE>(s)
        {
          n2=n;
          v2=new TYPE[n2+1];
          memcpy(v2,s.v2,n2);
        };
     ~s0_2()
        {
          delete [] v2; 
        };  
};

template <class TYPE>
class s1: public s0_1<TYPE>,public s0_2<TYPE>
{
  public:
      s1():s0_1<TYPE>():s0_2<TYPE>()
        {
        };
      s1(const s1   &s):s0_1<TYPE>(s):s0_2<TYPE>(s)
        {
        };
     ~s1(){};

};

вроде так, если правильно понял но
получилось ещё хуже 

size(s0  )=8
size(s0_1)=16  //вместо 12 
size(s0_2)=20  //вместо 16
size(s1  )=28   //вместо 20 как хотелось бы

вот и второй вопрос: 
куда уходят по 4 байта в классах s0_1 и s0_2 
что ещё дает это переопределие "virtual"

в том примере из ссылки такая-же ситуация:
Код

 class Base {
 protected:
   int data_;
 };
 
 class Der1 : public virtual Base {
 public:

 };
 
 class Der2 : public virtual Base {
 public:
 };
 
 class Join : public Der1, public Der2 {
 public:
   void method()
   {
      data_ = 1; 
   }
 };

size(Base)=4
size(Der1)=8  //откуда ещё 4-е байта?
size(Der2)=8
size(Join)=12 

во втором примере без данных ещё хуже:
size(Base)=4
size(Der1)=12
size(Der2)=12
size(Join)=20


PM MAIL WWW ICQ Skype   Вверх
nickless
Дата 5.6.2007, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


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

Репутация: 19
Всего: 181



Цитата(Programister0 @  5.6.2007,  17:19 Найти цитируемый пост)
куда уходят по 4 байта в классах s0_1 и s0_2

В классах с виртуальными функциями или в наследованых классах есть еще указатель на таблицу виртуальных методов (VMT), (это зависит от реализации и может быть по другому в разных компиляторах, но в большинстве это так).
Т.е.
size(s0<int>  )=8 // TYPE* + DWORD = 4 + 4
size(s0_1<int>)=16  //VMT* + TYPE* + base = 4 + 4 + 8
size(s0_2<int>)=20  //VMT* + TYPE* + DWORD + base = 4 + 4 + 4 + 8
size(s1<int>  )=28   //s0_1::VMT* + s01:(TYPE*) + s0_2::VMT* + s0_2:(TYPE* + DWORD) + base = 4 + 4 + 4 + 8 + 8
в общем всё правильно smile 

Цитата(Programister0 @  5.6.2007,  17:19 Найти цитируемый пост)
что ещё дает это переопределие "virtual"

Почитай дальше по ссылке, там есть примеры, например когда класс использует виртуальный метод дочернего класса, итд.

А вообще множественное наследование нужно использовать осторожно, только в особых случаях и если знаешь что делаешь smile 


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
archimed7592
Дата 6.6.2007, 00:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

Репутация: 58
Всего: 93



Цитата(Programister0 @  5.6.2007,  18:19 Найти цитируемый пост)
 s1():s0_1<TYPE>():s0_2<TYPE>()
если не ошибаюсь, писать нужно так:
Код
s1():s0_1<TYPE>(), s0_2<TYPE>()
а, раз у тебя s0 в единственном экземпляре(из-за виртуального наследования), то вот так:
Код
s1():s0<TYPE>(), s0_1<TYPE>(), s0_2<TYPE>()
иначе можешь получить не совсем то, что хочешь... например, вот здесь:
Цитата(Programister0 @  5.6.2007,  18:19 Найти цитируемый пост)
s1(const s1   &s):s0_1<TYPE>(s):s0_2<TYPE>(s)
ты получишь то же самое, что если написал бы
Код
s1(const s1   &s):s0<TYPE>(), s0_1<TYPE>(s), s0_2<TYPE>(s)
но, в действительности ты же хочешь получить вот это:
Код
s1(const s1   &s):s0<TYPE>(s), s0_1<TYPE>(s), s0_2<TYPE>(s)




Цитата(nickless @  5.6.2007,  20:30 Найти цитируемый пост)
А вообще множественное наследование нужно использовать осторожно, только в особых случаях и если знаешь что делаешь smile  
 smile  smile  smile 

Это сообщение отредактировал(а) archimed7592 - 6.6.2007, 00:27


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
Programister0
Дата 6.6.2007, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



большое спасибо вам о великие программеры: archimed7592, nickless, Rockie,  Damarus;
я вроде догнался с наслеованием и virtual'ами, - буду использовать только в крайних случаях, 
 но в своих классах: никогда - эт. точно;


И ещё что это у вас тут за система 
Цитата

Репутация: * [ + | — ]

мне типа надо нажать эти  + | —  - если понравились/помогли ответы, к чему все это.

ещё раз спасибо всем, вы мне очень помогли.
PM MAIL WWW ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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