Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.12.2012, 16:30   #1
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию Создание экземпляра класса по имени

Доброго времени суток.
Имеется шаблонный класс. Он является наследником базового абстрактного класса, в котором определены нужные методы.
Код:
//----------------------------------
//Базовый
//----------------------------------
class V
{
public:
    V(){}
    ~V(){}
    virtual string getName() = 0;
    virtual void notify() = 0;
    virtual void handle() = 0;
};
//----------------------------------
//Наследник
//----------------------------------
template <class T>
class E: public V
{
public:
    string getName();
    void notify();
    void handle();
};
//----------------------------------
//Отдельный
//----------------------------------
class B
{
public:
    B(){}
    void add(V *e)
    {
        tempName = e->getName();
        eList.push_back(e);
    }
    void go()
    {
        for (short i = 0; i < (short)evList.size(); i++)
        {
            eList[i]->handle();
        }
    }
private:
    string tempName;
    static vector <V*> eList;
};
Так оно всё работает замечательно, но при удалении наследника отдельный класс перестаёт функционировать(по понятным причинам).
Задачка следующего характера: перейти с указателей на базовый на экземпляры базового класса. Подскажите, возможно ли это?

Последний раз редактировалось Stilet; 11.12.2012 в 16:38.
Lasor вне форума Ответить с цитированием
Старый 11.12.2012, 17:00   #2
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Можно конструкцию, в которой сейчас используется E<T>, а хочется что-то другое?
Abstraction вне форума Ответить с цитированием
Старый 11.12.2012, 17:22   #3
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Код:
//--------------------------------
//Поток 1
//--------------------------------
class E_1:public E<E_1>
{
public:
    int someint;
};
E_1 *one;
one = new E_1;
one->someint = 1;
one->notify();
//--------------------------------
//Поток 2
//--------------------------------
class E_2:public E<E_2>
{
public:
    int someint;
};
E_2 *two;
two = new E_2;
two->someint = 2;
two->notify();
//--------------------------------
//Поток 3
//--------------------------------
B b;
b.go();
Примерно так.
Lasor вне форума Ответить с цитированием
Старый 11.12.2012, 17:33   #4
Granus
С++
Форумчанин
 
Аватар для Granus
 
Регистрация: 22.09.2008
Сообщений: 791
По умолчанию

Цитата:
Так оно всё работает замечательно, но при удалении наследника отдельный класс перестаёт функционировать(по понятным причинам).
Подробнее, что Вы здесь удаляете и что перестает работать?
Форматируйте код, будьте людьми.
Granus вне форума Ответить с цитированием
Старый 11.12.2012, 17:51   #5
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Я удаляю объекты one и two, ибо потоки заканчиваются.
Lasor вне форума Ответить с цитированием
Старый 11.12.2012, 21:43   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Lasor Посмотреть сообщение
Так оно всё работает замечательно, но при удалении наследника отдельный класс перестаёт функционировать(по понятным причинам).
Задачка следующего характера: перейти с указателей на базовый на экземпляры базового класса. Подскажите, возможно ли это?
Возможно. Но тебя не спасет. Получишь срезку.

У тебя ошибка архитектуры: нарушение прав владения объектами.

Ты создаешь экземпляры наследников. И скармливаешь их некоторому менеджеру - экземпляру класса B. Но он не владеет самими объектами.

Соответственно, при уничтожении этих объектов, менеджер ломается.

Лекарство:

1. Костыль: перед уничтожением объекта наследника, предупреждай об этом менеджера. Тогда он удалит у себя ненужный уже указатель, и сохранит работоспособность.

2. Хорошее решение: передай менеджеру право владением всеми теми объектами, с которыми он работает. Это означает, что наследники - собственность менеджера. Живут внутри его. И без его особого разрешения, никто их снаружи пригрохать не может.

3. Альтернативное решение: менеджер создает наследников. Наружу выдает интерфейсный указатель. Если снаружи интерфейсный указатель пригрохать, то перед гибелью, он успеет сообщить менеджеру о факте своей гибели. Менеджер соответственно, сможет принять меры и не поломается.

4. Решение в стиле ООП-с++:

Архитектура имеет вид: пользовательские механизмы, внешне ни с кем не связанные. Внутри себя они сами инициализируют ядро (менеджера). И общаются с ним по невидимой пользователю связи.

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

Ядро контролирует ресурсы. А пользовательские механизмы - лишь представление этих ресурсов для пользователей. А на самом деле - средство для связи с ядром.

Поскольку ядро не доступно пользователям, то снаружи его не возможно повредить.
_Bers вне форума Ответить с цитированием
Старый 11.12.2012, 23:42   #7
Perchik71
С++, Delphi
Форумчанин
 
Аватар для Perchik71
 
Регистрация: 24.11.2012
Сообщений: 495
По умолчанию

Код:
template <class T>
class E: public V
{
public:
    string getName();
    void notify();
    void handle();
};
в этом шаблоне класса нет смысла.

вот если его папа класс тоже был бы шаблонным и имел данную перемменую того типа, то другое дело.
Если помог, тут весы есть , Вам не сложно, а мне приятно.
Perchik71 вне форума Ответить с цитированием
Старый 12.12.2012, 12:19   #8
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Возможно. Но тебя не спасет. Получишь срезку.

У тебя ошибка архитектуры: нарушение прав владения объектами.

Ты создаешь экземпляры наследников. И скармливаешь их некоторому менеджеру - экземпляру класса B. Но он не владеет самими объектами.

Соответственно, при уничтожении этих объектов, менеджер ломается.

Лекарство:

1. Костыль: перед уничтожением объекта наследника, предупреждай об этом менеджера. Тогда он удалит у себя ненужный уже указатель, и сохранит работоспособность.

2. Хорошее решение: передай менеджеру право владением всеми теми объектами, с которыми он работает. Это означает, что наследники - собственность менеджера. Живут внутри его. И без его особого разрешения, никто их снаружи пригрохать не может.

3. Альтернативное решение: менеджер создает наследников. Наружу выдает интерфейсный указатель. Если снаружи интерфейсный указатель пригрохать, то перед гибелью, он успеет сообщить менеджеру о факте своей гибели. Менеджер соответственно, сможет принять меры и не поломается.

4. Решение в стиле ООП-с++:

Архитектура имеет вид: пользовательские механизмы, внешне ни с кем не связанные. Внутри себя они сами инициализируют ядро (менеджера). И общаются с ним по невидимой пользователю связи.

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

Ядро контролирует ресурсы. А пользовательские механизмы - лишь представление этих ресурсов для пользователей. А на самом деле - средство для связи с ядром.

Поскольку ядро не доступно пользователям, то снаружи его не возможно повредить.
Дело в том, что не имеется возможности запретить удалять наследники, с которыми работает менеджер, ибо они могут быть созданы пользователем/другим разработчиком где-либо локально.
Решение, которое видится мне - создавать копии (не бейте по голове) наследников и передавать их менеджеру по методу notify(). Задача менеджера - обработать все подписчики наследника методом handle() (подписчиков, разумеется, несколько).
Для этого, попробую использовать списки типов.
Если кто-нибудь может показать, как записывать копии, буду рад.
Lasor вне форума Ответить с цитированием
Старый 12.12.2012, 18:06   #9
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Держи:

http://ideone.com/tsEQTL

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

Код:
#include<iostream>
#include<vector>
 
    struct IObject
    {
        virtual ~IObject(){}
        virtual IObject* Clone()=0;
        virtual void Work()=0;
    };
    
    struct Concrete_Object1: IObject
    {
        virtual void Work()               { std::cout<<"Concrete_Object1: working\n";    }
        virtual ~Concrete_Object1()       { std::cout<<"Concrete_Object1: destroyed\n";  }
        virtual Concrete_Object1* Clone() { return new Concrete_Object1(*this);          }
    };
    struct Concrete_Object2: IObject
    {
        virtual void Work()               { std::cout<<"Concrete_Object2: working\n";    }
        virtual ~Concrete_Object2()       { std::cout<<"Concrete_Object2: destroyed\n";  }
        virtual Concrete_Object2* Clone() { return new Concrete_Object2(*this);          }
    };    
        
    struct Manager
    {
        ~Manager()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ delete mObj[n]; mObj[n] = 0l; }
        }
        
        void Connect(IObject* src){  mObj.push_back( src->Clone() ); }
        
        void Work()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ mObj[n]->Work(); }
        }
        std::vector<IObject*> mObj;
    };
 
 
int main()
{
   Manager man;
   IObject* agent1 = new Concrete_Object1();
   IObject* agent2 = new Concrete_Object2();
   
   man.Connect(agent1);
   man.Connect(agent2);
   
   delete agent1;
   delete agent2;
   
   man.Work();
   
   return 0;
}

Последний раз редактировалось _Bers; 12.12.2012 в 18:11.
_Bers вне форума Ответить с цитированием
Старый 13.12.2012, 10:41   #10
Lasor
Пользователь
 
Регистрация: 05.12.2012
Сообщений: 67
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Держи:

http://ideone.com/tsEQTL

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

Код:
#include<iostream>
#include<vector>
 
    struct IObject
    {
        virtual ~IObject(){}
        virtual IObject* Clone()=0;
        virtual void Work()=0;
    };
    
    struct Concrete_Object1: IObject
    {
        virtual void Work()               { std::cout<<"Concrete_Object1: working\n";    }
        virtual ~Concrete_Object1()       { std::cout<<"Concrete_Object1: destroyed\n";  }
        virtual Concrete_Object1* Clone() { return new Concrete_Object1(*this);          }
    };
    struct Concrete_Object2: IObject
    {
        virtual void Work()               { std::cout<<"Concrete_Object2: working\n";    }
        virtual ~Concrete_Object2()       { std::cout<<"Concrete_Object2: destroyed\n";  }
        virtual Concrete_Object2* Clone() { return new Concrete_Object2(*this);          }
    };    
        
    struct Manager
    {
        ~Manager()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ delete mObj[n]; mObj[n] = 0l; }
        }
        
        void Connect(IObject* src){  mObj.push_back( src->Clone() ); }
        
        void Work()
        {
            const size_t size = mObj.size();
            for(size_t n=0;n<size;++n){ mObj[n]->Work(); }
        }
        std::vector<IObject*> mObj;
    };
 
 
int main()
{
   Manager man;
   IObject* agent1 = new Concrete_Object1();
   IObject* agent2 = new Concrete_Object2();
   
   man.Connect(agent1);
   man.Connect(agent2);
   
   delete agent1;
   delete agent2;
   
   man.Work();
   
   return 0;
}
Интересный выход. Спасибо. Всё-таки, С++ действительно позволяет написать пару строк и потом сказать: "Это гениально!".
http://ideone.com/tsEQTL пока недоступен, увы...
Lasor вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание экземпляра класса biohazard120 Общие вопросы Delphi 11 15.09.2012 13:23
C#(перехват нового экземпляра класса StackOverflowException) Anett// Помощь студентам 0 12.05.2011 22:26
Освобождение памяти от экземпляра класса Mixim Общие вопросы .NET 8 05.01.2011 17:27
удаление экземпляра класса Juffin Общие вопросы Delphi 5 02.11.2010 11:57
ListBox, привязка экземпляра класса к Item. Возможно ли? Casper-SC Общие вопросы .NET 1 24.05.2010 10:40