Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Pavel.fromBy
13 / 13 / 1
Регистрация: 31.12.2011
Сообщений: 83
#1

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

29.04.2012, 20:04. Просмотров 797. Ответов 9
Метки нет (Все метки)

Добрый вечер, уважаемые форумчане! Сразу код; вопрос ниже...

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;, то компилятор ругнется, что левый операнд не может быть изменен (ибо это константа), а из этого следует, что она уже создана (но не инициализирована!!!). Константа инициализируется сразу после вызова конструктора базового класса в блоке инициализации, но она была УЖЕ создана (в конструкторе базового я вывел ее на консоль... получил мусор!)... Это ведь противоречит тому, что константы должны быть инициализированы сразу же после определения.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.04.2012, 20:04
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Инициализация членов производного кл. из конструктора базового кл. (C++):

Инициализация конструктора базового класса - C++
class animal { public: animal(int a):ianimal(a){} protected: int ianimal; }; class bird:public animal

Конструкторы базового и производного класса - C++
class first { public: first(int a):first(a){} void Setfirst(int a){first=a;} int Getfirst(){return first;} private: ...

Вызов методов базового и производного классов - C++
Народ, объясните тупому механику раннего связывания. Вывод программы, что ниже, 22. Хотя если вызывать непосредственно функцию f, будет...

Вызов методов производного класса из базового - C++
Возможно ли, чтобы class A { void f1() { f2();//если вызвано из B, то вызывается B::f2(), а не A::f2() } void f2(){} }

Отрабатывает оператор базового, а не производного класса - C++
Здравствуйте! Собственно, вопрос в следующем. Я перегрузил оператор потокового вывода для базового и для производного класса. При выводе...

Объекты производного класса не наследуют методы базового - C++
Доброго всем дня! Вот такая у меня проблема возникла - объекты производного класса свободно вычитаются, но почему-то не складываются,...

9
panicwassano
594 / 562 / 20
Регистрация: 07.11.2010
Сообщений: 2,004
29.04.2012, 20:19 #2
смысл вообще этого кода? ТС понимает, что такое наследование? или вы от балды такое пишете

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

Добавлено через 1 минуту
Цитата Сообщение от panicwassano Посмотреть сообщение
базовый класс не знает о производных ничего
Почему тогда я могу инициализировать его непостоянные члены? Смотрите этот "бессмысленный код". И если бы он ничего не знал о производном, то он бы не знал, что переменная a - константа.
0
panicwassano
594 / 562 / 20
Регистрация: 07.11.2010
Сообщений: 2,004
29.04.2012, 20:22 #4
Цитата Сообщение от Pavel.fromBy Посмотреть сообщение
Константа инициализируется сразу после вызова конструктора базового класса в блоке инициализации
откуда базового если у вас она в производном, а то что у вас вывелся мусор еще не говорит о том что вы обратились по нужному адресу
0
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). Первым идет вызов базового конструктора, потом иниц. константа.
0
grizlik78
Эксперт С++
1982 / 1475 / 126
Регистрация: 29.05.2011
Сообщений: 3,048
29.04.2012, 20:30 #6
Цитата Сообщение от Pavel.fromBy Посмотреть сообщение
panicwassano, ((Two *)this)->b = 20; Как вы объясните это?
Это "хак". Базовый класс не может знать, кто его унаследует, так что вряд ли такой код можно назвать корректным. Скорее всего это говорит о плохом дизайне программы. И, кстати, если объявить a и b закрытыми (private), как это обычно и бывает, то компилятор справедливо возмутится.
А приведение типа указателя в стиле Си это очень мощная штука, и очень опасная в неправильных руках.
1
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
Преподаватель грамотный, вряд ли бы просто так стал юзать этот "хак".
0
grizlik78
Эксперт С++
1982 / 1475 / 126
Регистрация: 29.05.2011
Сообщений: 3,048
29.04.2012, 20:44 #8
fHwnd и fHdc засунуть в Policy, можно даже открытыми, тогда проблемы нет. Большого смысла в наследовании, кстати, тоже не видно, можно обойтись включением.
1
Pavel.fromBy
13 / 13 / 1
Регистрация: 31.12.2011
Сообщений: 83
29.04.2012, 20:53  [ТС] #9
grizlik78, еще раз спасибо. Наверное так и сделаю, хотя завтра еще у преподавателя спрошу...
0
grizlik78
Эксперт С++
1982 / 1475 / 126
Регистрация: 29.05.2011
Сообщений: 3,048
29.04.2012, 20:56 #10
Вот, кстати, обе политики можно унаследовать от одной базовой, в которой будут объявлены переменные и, возможно, функции доступа к ним (хотя сеттеры/геттеры может уже и лишнее).
0
29.04.2012, 20:56
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.04.2012, 20:56
Привет! Вот еще темы с ответами:

Вызов виртуального метода базового класса из указателя производного - C++
Допустим есть такой код: #include &lt;iostream&gt; class Base { public: virtual void f() { std::cout &lt;&lt; &quot;Base\n&quot;; } ...

Как узнать тип производного класса в функции базового - C++
Всем привет! Есть иерархия классов: class1 -&gt; class2-&gt;class3 class2-&gt;class4 class2-&gt;class5 Где...

Наследование: почему вызывается метод базового класса, а не производного? - C++
Всем привет, такой вопрос, почему вызывается в данном коде метод базового класса, а не производного (без указания ключевого слова virtual...

Можно ли из базового класса обратится к виртуальному методу производного? - C++
Можно ли из базового класса обратится к виртуальному методу производного? И если да то как (на примере класса A). Polym.cpp #include...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru