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

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

Войти
Регистрация
Восстановить пароль
 
 
newbie666
Заблокирован
#1

Виртуальные конструкторы или выбор паттерна проектирования - C++

09.04.2014, 14:01. Просмотров 627. Ответов 17
Метки нет (Все метки)

Vi danno il benvenuto signori!
Ну так вот. Терзают меня сомнения на счёт наследования в одной программке ....
См. картинку, допустим есть какая - то иерархия классов, ну они там наследуются как - то по своему -ну да не суть.
Цель: нужно, единожды создать всю иерархию классов, тоесть единожды вызвав их все конструкторы, сформировать иерархическую структуру классов, чтоб в каждом дочернем классе были унаследованы от уже проинициализированного родителя данные ... Фишка в том, что дочерних однотипных классов на одном уровне наследования может быть много, тоесть по идее если создавать каждый раз нового "сынка", он вызовет конструктор "папаши", что ясен пень не допустимо, т.к. папаша должен быть всегда один, а сынков - много...
Я так подумал, что для таких целей вообще наследование не подходит - проще хранить указатели на все другие классы в одном каком - то, базовом например, да и всё ..
Кто что думает?
0
Миниатюры
Виртуальные конструкторы или выбор паттерна проектирования  
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.04.2014, 14:01
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Виртуальные конструкторы или выбор паттерна проектирования (C++):

Объектно-ориентированного проектирования и проектирования на основе структур данных - C++
Помогите решить задание, так как вообще не понимаю, что тут можно сделать. Решить задание с помощью объектно-ориентированного...

виртуальные и чисто виртуальные функции - C++
Чем они отличаются?? если можно, с примерами. И как из виртуальной функции сделать чисто виртуальную? #include <iostream> using...

Реализация паттерна проектирования цепочка обязаностей (chain of responsibility) - Java SE
Привет. Есть небольшой набросок паттерна проектирования цепочки обязанностей, написан на JavaScript, и нужно его адаптировать на Java,...

Выбор паттерна - ООП и паттерны
Добрый день! Подскажите, правильный ли паттерн я выбрал под задачу? В обобщенном варианте суть задачи такая. В момент старта...

Выбор паттерна - ООП и паттерны
Здравствуйте, у меня возник вопрос с выбором паттерна(ов) для следующей задачи: есть некоторая форма отображения (View), на которой...

Выбор паттерна для планировщика - PHP ООП
Проектирую модуль который будет выполнять функцию планировщика, т.е. так называемый планировщик задач для человека. Все относительно...

17
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,095
09.04.2014, 14:09 #2
Цитата Сообщение от newbie666 Посмотреть сообщение
дочерних однотипных классов на одном уровне наследования может быть много, тоесть по идее если создавать каждый раз нового "сынка", он вызовет конструктор "папаши", что ясен пень не допустимо, т.к. папаша должен быть всегда один, а сынков - много...
Смешали в кучу иерархию классов и состояние объектов.
Если есть иерархия классов, то конструктор родителя обязан вызываться каждый раз при создании объекта дочернего класса.
Если у Вас есть какие-то общие для всех константные данные - их можно инициализировать где-нибудь один раз и передавать объектам указатель на них при конструировании.
0
newbie666
Заблокирован
09.04.2014, 14:21  [ТС] #3
Цитата Сообщение от 0x10 Посмотреть сообщение
Если у Вас есть какие-то общие для всех константные данные - их можно инициализировать где-нибудь один раз и передавать объектам указатель на них при конструировании.
это то понятно, вот по этому сейчас у меня все классы одного уровня иерархии без всякого наследования.
Я при создание любого класса передаю в него указатель на основной класс, где хранятся все указатели на другие классы .... Так просто в базовых классах напрягает писать иногда типа
C++
1
base->renderer->show(трулялля) и т д
когда хотелось просто писать show (труляля) :-))
Думаю, тут надо мутить виртуальные конструкторы ...

Добавлено через 2 минуты
Цитата Сообщение от 0x10 Посмотреть сообщение
конструктор родителя обязан вызываться каждый раз при создании объекта дочернего класса.
ваще наследование - вещь сугубо специфическая... Вот нахрена от чего - то наследоваться, что каждый раз родительский конструктор вызывался ... Не проще всю инфу в самом классе проинициализировать без родителя вообще.... Конечно, тут есть профит в приведение типов, типа я в функцию передаю указатель типа родителя, а в функции привожу в зависимости от поля типа объекта в этом родителе указатель к нужному классу..... но это сомнительный профит
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,095
09.04.2014, 14:31 #4
Цитата Сообщение от newbie666 Посмотреть сообщение
в функции привожу в зависимости от поля типа объекта в этом родителе указатель к нужному классу..... но это сомнительный профит
Это вообще антипаттерн, зачем так делать?
0
newbie666
Заблокирован
09.04.2014, 14:45  [ТС] #5
Цитата Сообщение от 0x10 Посмотреть сообщение
Это вообще антипаттерн, зачем так делать?
ну а как ты сделаешь?
Вот посмотри на схему в первом посте, допусти есть базовый класс Miracle, есть два наследника Renderer и GameProcesor. Мне нужно чтоб в моей программе всегда был один экземпляр и Miracle и Renderer и GameProcesor, и хотелось бы, чтоб в каждом из наследников были данные из Miracle. Причём заранее что будет в Miracle - неизвестно, так как проект на стадии проектирования, каждый раз передавать тонну параметров в наследников - не коширно, передавать указатель на базовый Miracle - ну так я ща так и делаю... А вот хотелось бы, чтоб , ну хрен с остальными, что допустим эти три классы существовали в единственном экземпляре и в каждом наследнике были унаследованные данные из ОДНОГО И ТОГО ЖЕ базового класса Miracle.
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,095
09.04.2014, 14:48 #6
Цитата Сообщение от newbie666 Посмотреть сообщение
Мне нужно чтоб в моей программе всегда был один экземпляр и Miracle и Renderer и GameProcesor
Сделать закрытыми конструкторы и оператор присваивания. Везде, где нужны - передавать указатели или ссылки на них.

Цитата Сообщение от newbie666 Посмотреть сообщение
каждый раз передавать тонну параметров в наследников - не коширно
Сделать один объект класса Context, где разместить общие данные. Указатель или ссылку на него передавать в классы.

Добавлено через 25 секунд
Из требований я повода для наследования не вижу.
0
newbie666
Заблокирован
09.04.2014, 14:55  [ТС] #7
Цитата Сообщение от 0x10 Посмотреть сообщение
Сделать один объект класса Context, где разместить общие данные. Указатель или ссылку на него передавать в классы.
ну так я и ща делаю, яж говорю.
Цитата Сообщение от 0x10 Посмотреть сообщение
Сделать закрытыми конструкторы и оператор присваивания.
это понятно, но защищать что - то от самого себя я не стану :-)

Вот смотри, допустим есть три класса:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Base
{
public:
    Base(){DATA = rand();};
    ~Base(){};
    int DATA;
};
 
class Child1 : public Base
{
public:
    Child1(){};
    ~Child1(){};
    int GetData(){return DATA;}
};
 
class Child2 : public Base
{
public:
    Child2(){};
    ~Child2(){};
    int GetData(){return DATA;}
};
Мне нужно создать по одному экземпляру каждого класса, но чтоб в экземплярах классов наследников функция GetDate() возвращала одно и тоже число базового класса.

C++
1
2
3
4
5
Base *base; //как то создать
Child1 *child1; //как то создать
Child2 *child2; //как то создать
if(child1->GetData() != child2->GetData())
    std::cout << "SHIT :-)" << std::endl;
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,095
09.04.2014, 15:25 #8
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
#include <iostream>
#include <memory>
 
class Base {
public:
    Base(const std::shared_ptr<int>& sd) : shared_data_{sd} { }
    int& GetData() const { return *shared_data_; }
 
private:
    std::shared_ptr<int> shared_data_;
};
 
class C1 : public Base {
public:
    C1(const std::shared_ptr<int>& sd) : Base{sd} {}
};
 
class C2 : public Base {
public:
    C2(const std::shared_ptr<int>& sd) : Base{sd} {}
};
 
class Factory {
public:
    Factory() : shared_data_{std::make_shared<int>(42)} {}
    
    C1 CreateC1() const { return C1(shared_data_); }
    C2 CreateC2() const { return C2(shared_data_); }
private:
    std::shared_ptr<int> shared_data_;
};
 
 
int main() {
    Factory f;
    
    C1 c1 = f.CreateC1();
    C2 c2 = f.CreateC2();
    
    std::cout << "C1: " << c1.GetData() << std::endl;
    std::cout << "C2: " << c2.GetData() << std::endl;
    
    c1.GetData() = 10;
    
    std::cout << "C1: " << c1.GetData() << std::endl;
    std::cout << "C2: " << c2.GetData() << std::endl;
    
    
    return 0;
}
http://ideone.com/l5n6qe
0
newbie666
Заблокирован
09.04.2014, 15:36  [ТС] #9
Цитата Сообщение от 0x10 Посмотреть сообщение
shared_data_{sd} { }
В списке инициализации значения присваиваются в круглых скобках, а не в фигурных
Ну да ладно, ну ты хоть понимаешь, что это тоже самое, как и у меня сейчас? Тоесть есть главный класс, в котором хранятся указатели на все другие....
Я для понта у себя тоже мог бы написать, типа в главном классе есть функция QueryInterface, которая мне б возвращала указатель на любой из классов, указатель на который есть в основном ....
Мне думаю подошёл бы downcasting, но уж очень криво он работает, точнее вообще нормально не работает ...
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,095
09.04.2014, 15:43 #10
Цитата Сообщение от newbie666 Посмотреть сообщение
В списке инициализации значения присваиваются в круглых скобках, а не в фигурных
Hello, C++11. Я специально ниже указал ссылку на ideone как пруф компилируемости.

Цитата Сообщение от newbie666 Посмотреть сообщение
Ну да ладно, ну ты хоть понимаешь, что это тоже самое, как и у меня сейчас?
Цитата Сообщение от newbie666 Посмотреть сообщение
Мне думаю подошёл бы downcasting, но уж очень криво он работает, точнее вообще нормально не работает ...
В предыдущих постах чередование запросов: то "мне нужны шареные данные", то "мне нужно знать тип во время выполнения". Чтобы не даункастить, есть паттерн visitor.
0
newbie666
Заблокирован
09.04.2014, 15:58  [ТС] #11
На самом деле в даункастинге нет ничего плохого.
Но вот кто - нибуть мне может внятно объяснить, почему в таком случае вылетает аксес виолэйшен?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base
{
public:
    Base(){};
    ~Base(){};  
};
class Child : public Base
{
public:
    Child();
    ~Child();
    std::vector<int> childData;
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    Base *base = new Base;
    Child *child = static_cast<Child*>(base);   
    child->childData.push_back(rand()); // Access violation!
    
    return 0;
}
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,095
09.04.2014, 16:03 #12
newbie666, потому что фактический тип - Base, у которого нет поля, к которому Вы обращаетесь.

Добавлено через 1 минуту
Цитата Сообщение от newbie666 Посмотреть сообщение
На самом деле в даункастинге нет ничего плохого.
И тут же:
Цитата Сообщение от newbie666 Посмотреть сообщение
почему в таком случае вылетает аксес виолэйшен?
0
newbie666
Заблокирован
09.04.2014, 16:06  [ТС] #13
Цитата Сообщение от 0x10 Посмотреть сообщение
потому что фактический тип - Base, у которого нет поля, к которому Вы обращаетесь.
не верно, т.к. если сделать так, то всё ок:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base
{
public:
    Base(){};
    ~Base(){};  
};
class Child : public Base
{
public:
    Child();
    ~Child();
    std::vector<int> childData;
    int x;
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    Base *base = new Base;
    Child *child = static_cast<Child*>(base);       
    child->x = 3;   
    return 0;
}
тут наверное фишка в выделенной памяти под Base, точнее в её ограничение ... Т.к. vector динамический выделяет память ...
0
0x10
2479 / 1652 / 248
Регистрация: 24.11.2012
Сообщений: 4,095
09.04.2014, 16:08 #14
У вас не был сконструирован объект класса Child - следовательно, не было вызвано конструкторов для его полей. Получите UB.
0
newbie666
Заблокирован
09.04.2014, 16:11  [ТС] #15
Цитата Сообщение от 0x10 Посмотреть сообщение
У вас не был сконструирован объект класса Child - следовательно, не было вызвано конструкторов для его полей. Получите UB.
воо плавно переходим к цели данного треда Как перевести базовый класс в дочерний, при этом:
1. вызвав класс дочернего
2. не вызвав класс базового
3. имея возможность работать с данными базового класса в дочернем
0
09.04.2014, 16:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.04.2014, 16:11
Привет! Вот еще темы с ответами:

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

Выбор интрументария для 3D проектирования строительных сооружений - САПР
привет всем! подскажите пожалуйста для 3D проектирования строительных сооружений и в частности вентиляционных систем какой инструмент...

Конструкторы должны быть паблик или приват? - Java SE
и вообще нужно ли их использовать? может лучше сразу инициализировать все переменные или устанавливать ии через метод сеттер

Сервер или пк под виртуальные машины - Серверы
Задача: нужно 8-10 офисных пк в одной машине. Т.е. работает один человек, и у него несколько систем, большая часть которых выполняет...


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

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

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