Форум программистов, компьютерный форум CyberForum.ru

Инициализация членов производного кл. из конструктора базового кл. - C++

Войти
Регистрация
Восстановить пароль
 
Pavel.fromBy
 Аватар для Pavel.fromBy
13 / 13 / 1
Регистрация: 31.12.2011
Сообщений: 83
29.04.2012, 20:04     Инициализация членов производного кл. из конструктора базового кл. #1
Добрый вечер, уважаемые форумчане! Сразу код; вопрос ниже...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
 
using namespace std;
 
class One
{
public:
    One(int _a);
};
 
class Two: public One
{
public:
    const int a;
    int b;
    Two(int _a): One(_a), a(3)
    {
        cout << "Two constrcutor!" << endl;
        cout << a << endl;
        cout << b << endl;
    }
};
 
One::One(int _a)
{
    cout << "One constructor!" << endl;
//  ((Two *)this)->a = _a;   не работает!
    cout << ((Two *)this)->a << endl;
    ((Two *)this)->b = 20;
}
 
int main()
{
    Two a1(2);
}
Почему я могу инициализировать непостоянные члены производного класса из конструктора базового? Почему я ВООБЩЕ их могу инициализировать? На сколько мне известно, при создании объекта производного класса сразу создается "базовая" часть, а потом "производная" (тут я может быть и не прав, не утверждаю). Откуда конструктор базового класса знает, что там творится у производного...?
Далее... Если выше раскомментировать строку ((Two *)this)->a = _a;, то компилятор ругнется, что левый операнд не может быть изменен (ибо это константа), а из этого следует, что она уже создана (но не инициализирована!!!). Константа инициализируется сразу после вызова конструктора базового класса в блоке инициализации, но она была УЖЕ создана (в конструкторе базового я вывел ее на консоль... получил мусор!)... Это ведь противоречит тому, что константы должны быть инициализированы сразу же после определения.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.04.2012, 20:04     Инициализация членов производного кл. из конструктора базового кл.
Посмотрите здесь:

Вызов конструктора базового класса C++
Инициализация конструкторов производного класса C++
Вызов виртуального метода базового класса из указателя производного C++
Вызов методов производного класса из базового C++
Конструкторы базового и производного класса C++
Инициализация конструктора базового класса C++
C++ Определение конструктора копирования для производного класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
panicwassano
591 / 559 / 20
Регистрация: 07.11.2010
Сообщений: 2,004
29.04.2012, 20:19     Инициализация членов производного кл. из конструктора базового кл. #2
смысл вообще этого кода? ТС понимает, что такое наследование? или вы от балды такое пишете

Добавлено через 2 минуты
Цитата Сообщение от Pavel.fromBy Посмотреть сообщение
((Two *)this)->a = _a; не работает!
константные членые инициализируются только в списке инициализации, базовый класс не знает о производных ничего!
Pavel.fromBy
 Аватар для Pavel.fromBy
13 / 13 / 1
Регистрация: 31.12.2011
Сообщений: 83
29.04.2012, 20:21  [ТС]     Инициализация членов производного кл. из конструктора базового кл. #3
panicwassano, я понимаю, что такое наследование. Смысл этот код несет исключительно для вопроса. Могу предоставить код, где это используется со смыслом. Это если я вас правильно понял...

Добавлено через 1 минуту
Цитата Сообщение от panicwassano Посмотреть сообщение
базовый класс не знает о производных ничего
Почему тогда я могу инициализировать его непостоянные члены? Смотрите этот "бессмысленный код". И если бы он ничего не знал о производном, то он бы не знал, что переменная a - константа.
panicwassano
591 / 559 / 20
Регистрация: 07.11.2010
Сообщений: 2,004
29.04.2012, 20:22     Инициализация членов производного кл. из конструктора базового кл. #4
Цитата Сообщение от Pavel.fromBy Посмотреть сообщение
Константа инициализируется сразу после вызова конструктора базового класса в блоке инициализации
откуда базового если у вас она в производном, а то что у вас вывелся мусор еще не говорит о том что вы обратились по нужному адресу
Pavel.fromBy
 Аватар для Pavel.fromBy
13 / 13 / 1
Регистрация: 31.12.2011
Сообщений: 83
29.04.2012, 20:24  [ТС]     Инициализация членов производного кл. из конструктора базового кл. #5
panicwassano, ((Two *)this)->b = 20; Как вы объясните это?

Добавлено через 52 секунды
Цитата Сообщение от panicwassano Посмотреть сообщение
откуда базового если у вас она в производном
Вы опять меня не поняли. Я про строку Two(int _a): One(_a), a(3). Первым идет вызов базового конструктора, потом иниц. константа.
grizlik78
Эксперт С++
 Аватар для grizlik78
1888 / 1420 / 103
Регистрация: 29.05.2011
Сообщений: 2,970
29.04.2012, 20:30     Инициализация членов производного кл. из конструктора базового кл. #6
Цитата Сообщение от Pavel.fromBy Посмотреть сообщение
panicwassano, ((Two *)this)->b = 20; Как вы объясните это?
Это "хак". Базовый класс не может знать, кто его унаследует, так что вряд ли такой код можно назвать корректным. Скорее всего это говорит о плохом дизайне программы. И, кстати, если объявить a и b закрытыми (private), как это обычно и бывает, то компилятор справедливо возмутится.
А приведение типа указателя в стиле Си это очень мощная штука, и очень опасная в неправильных руках.
Pavel.fromBy
 Аватар для Pavel.fromBy
13 / 13 / 1
Регистрация: 31.12.2011
Сообщений: 83
29.04.2012, 20:36  [ТС]     Инициализация членов производного кл. из конструктора базового кл. #7
grizlik78, спасибо.
Ниже я приведу код, где это используется "со смыслом" . Прошу прощения, что это в ветке C++, но вопрос я уже тут задал, да и задавал по консольке.
Ниже код Win32 API. Преподаватель в универе сказал использовать контекст устройства с этим кодом. Это оправдывается тем, что если выбросить исключение до освобождения контекста устройства, то память останется занятой. Код, который приведен ниже, позволяет обойти эту вещь, ибо при выбросе исключения вызываются деструкторы объектов, объявленных до его возникновения (Опять может некорректно написал...).


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//---------------------------------------------------------------------------
 
#ifndef KHdcH
#define KHdcH
 
#define STRICT
#include <windows.h>
#include <windowsx.h>
 
//---------------------------------------------------------------------------
 
template <typename Policy>  class Khdc;
 
class plcGetDC
{public:   
  inline plcGetDC(HWND ahwnd);
 
 protected:
  ~plcGetDC();
 
};
//------------------------------------------------------------------------------
 
class plcBeginPaint
{public:
  inline plcBeginPaint(HWND ahwnd);
 
 protected:
  ~plcBeginPaint();
 
 private:
  PAINTSTRUCT ps;
};
//------------------------------------------------------------------------------
 
template <typename Policy>
class Khdc: public Policy
{
  typedef Policy KPolicyType;
 
  friend KPolicyType;
 
 public:
  Khdc (HWND hwnd): Policy(hwnd) { }
  ~Khdc() {  }
 
  operator HDC& ()  { return fHdc; }
 
 private:
  HWND fHwnd;
   HDC fHdc;
};
 
//------------------------ inline implementation -------------------------------
 
  typedef Khdc<plcBeginPaint>   KBeginPaint;
  typedef Khdc<plcGetDC>   KGetDC;
 
//---------------------------- plcGetDC ----------------------------------------
inline
plcGetDC::plcGetDC(HWND ahwnd)
    {reinterpret_cast<Khdc<plcGetDC> *>(this)->fHwnd = ahwnd;
     reinterpret_cast<Khdc<plcGetDC> *>(this)->fHdc = GetDC(ahwnd);
    }
 
inline
plcGetDC::~plcGetDC()
  {Khdc<plcGetDC> *const& This = reinterpret_cast<Khdc<plcGetDC> *const&>(this);
   //ReleaseDC( reinterpret_cast<Khdc<plcGetDC> *>(this)->fHwnd, reinterpret_cast<Khdc<plcGetDC> *>(this)->fHdc);
   ReleaseDC( This->fHwnd, This->fHdc);
  }
 
//---------------------------- plcBeginPaint -----------------------------------
inline
plcBeginPaint::plcBeginPaint(HWND ahwnd)
    {((Khdc<plcBeginPaint> *)this)->fHwnd = ahwnd;
     ((Khdc<plcBeginPaint> *)this)->fHdc = BeginPaint(ahwnd, &ps);
    }
 
inline
plcBeginPaint::~plcBeginPaint() { EndPaint(((Khdc<plcBeginPaint> *)this)->fHwnd, &ps); }
#endif
Преподаватель грамотный, вряд ли бы просто так стал юзать этот "хак".
grizlik78
Эксперт С++
 Аватар для grizlik78
1888 / 1420 / 103
Регистрация: 29.05.2011
Сообщений: 2,970
29.04.2012, 20:44     Инициализация членов производного кл. из конструктора базового кл. #8
fHwnd и fHdc засунуть в Policy, можно даже открытыми, тогда проблемы нет. Большого смысла в наследовании, кстати, тоже не видно, можно обойтись включением.
Pavel.fromBy
 Аватар для Pavel.fromBy
13 / 13 / 1
Регистрация: 31.12.2011
Сообщений: 83
29.04.2012, 20:53  [ТС]     Инициализация членов производного кл. из конструктора базового кл. #9
grizlik78, еще раз спасибо. Наверное так и сделаю, хотя завтра еще у преподавателя спрошу...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.04.2012, 20:56     Инициализация членов производного кл. из конструктора базового кл.
Еще ссылки по теме:

Можно ли из базового класса обратится к виртуальному методу производного? C++
Как узнать тип производного класса в функции базового C++
Вынести реализацию конструктора производного класса C++
Наследование: почему вызывается метод базового класса, а не производного? C++
C++ Вызов методов базового и производного классов

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
grizlik78
Эксперт С++
 Аватар для grizlik78
1888 / 1420 / 103
Регистрация: 29.05.2011
Сообщений: 2,970
29.04.2012, 20:56     Инициализация членов производного кл. из конструктора базового кл. #10
Вот, кстати, обе политики можно унаследовать от одной базовой, в которой будут объявлены переменные и, возможно, функции доступа к ним (хотя сеттеры/геттеры может уже и лишнее).
Yandex
Объявления
29.04.2012, 20:56     Инициализация членов производного кл. из конструктора базового кл.
Ответ Создать тему
Опции темы

Текущее время: 03:20. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru