Одесса: 1°С (вода 8°С)
Киев: 0°С
Львов: -3°С

Тема: Вопрос знатокам с++

Ответить в теме
Страница 1 из 2 1 2 ПоследняяПоследняя
Показано с 1 по 20 из 31
  1. Вверх #1
    Модератор
    Мистер Одесский Форум
    Аватар для maxx™
    Пол
    Мужской
    Адрес
    Одесса
    Возраст
    38
    Сообщений
    23,360
    Репутация
    6089

    По умолчанию Вопрос знатокам с++

    Как на с++ создать объект, если имя класса становится известным только на этапе выполнения (имя родительского класса известно и в процессе написания программы)? Это вообще возможно?


  2. Вверх #2
    Посмотри паттерн "абстрактная фабрика". Если в новом классе не появляются новые публичные методы, то вполне может подойти.
    Если не подойдет под твою задачу, то посмотри среди других порождающих паттернов.

    На Вики это:
    Абстрактная_фабрика_(шаблон_проектирования)
    Порождающие шаблоны проектирования

    Книжка: Приемы объектно-ориентированного проектирования. Паттерны проектирования

  3. Вверх #3
    Модератор
    Мистер Одесский Форум
    Аватар для maxx™
    Пол
    Мужской
    Адрес
    Одесса
    Возраст
    38
    Сообщений
    23,360
    Репутация
    6089
    Цитата Сообщение от DiMomite Посмотреть сообщение
    Посмотри паттерн "абстрактная фабрика". Если в новом классе не появляются новые публичные методы, то вполне может подойти.
    Если не подойдет под твою задачу, то посмотри среди других порождающих паттернов.

    На Вики это:
    Абстрактная_фабрика_(шаблон_проектирования)
    Порождающие шаблоны проектирования

    Книжка: Приемы объектно-ориентированного проектирования. Паттерны проектирования
    Абстрактная фабрика это конечно хорошо, но смотрим туже вики:
    Код:
    int main()
    {
            ToyotaFactory   toyotaFactory;
            FordFactory     fordFactory;
             use (&toyotaFactory);
            use (&fordFactory);
             return 0;
    }
    В этом примере фабрика прописывется в коде, а потом функции use передается ссылка на ту или иную фабрику.
    Например в Java делаем так:
    String name = "имя класса"
    Class classDefinition = null;
    classDefinition = Class.forName("packagename." + name);
    myClass c = (myClass) classDefinition.newInstance();
    c.execute();
    И при выполнении программы класс будет найден во время выполнения. Естественно в интерфейсе myClass описан метод execute и предполагается что все загруженые этим куском кода классы будут этот интерфейс поддреживать.

  4. Вверх #4
    Можно еще так делать.
    При этом после добавления нового типа его создание надо прописывать только в одной месте - в фабрике.

    Код:
    #include <iostream>
    
    // интерфейс для всех создаваемых объектов
    class IObjectable
    {
    public:
        IObjectable();
        virtual ~IObjectable() = 0;
    
        // interface section
    public:
        virtual void execute() = 0;
    };
    
    IObjectable::IObjectable() {}
    IObjectable::~IObjectable() {}
    
    
    class ClassA : public IObjectable
    {
    public:
        virtual void execute() { std::cout << "This is ClassA execute()\n"; }
    };
    
    class ClassB : public IObjectable
    {
    public:
        virtual void execute() { std::cout << "This is ClassB execute()\n"; }
    };
    
    // фабрика
    class ObjectFactory
    {
    private:
        ObjectFactory();
    
    public:
        static IObjectable * getObjectInstance(char * className);
    };
    
    IObjectable * ObjectFactory::getObjectInstance(char * className)
    {
        if (0 == strcmp(className, "ClassA"))
            return new ClassA;
    
        if (0 == strcmp(className, "ClassB"))
            return new ClassB;
    
        return 0;
    }
    
    int main(int argc, char *argv[])
    {
    
        std::cout << "Start\n";
    
        IObjectable * myObject = 0;
    
        myObject = ObjectFactory::getObjectInstance("ClassA");
        if (myObject)
            myObject->execute();
        delete myObject;
        myObject = 0;
    
        myObject = ObjectFactory::getObjectInstance("ClassB");
        if (myObject)
            myObject->execute();
        delete myObject;
        myObject = 0;
    
        return 0;
    }
    Последний раз редактировалось DiMomite; 02.10.2011 в 20:11.

  5. Вверх #5
    Модератор
    Мистер Одесский Форум
    Аватар для maxx™
    Пол
    Мужской
    Адрес
    Одесса
    Возраст
    38
    Сообщений
    23,360
    Репутация
    6089
    Цитата Сообщение от DiMomite Посмотреть сообщение
    Можно еще так делать.
    При этом после добавления нового типа его создание надо прописывать только в одной месте - в фабрике.
    Т.е. получается на с++ в принципе невозможно после создания класса не лезть в код и прописывать ifы?

  6. Вверх #6
    Модератор
    Мистер Одесский Форум
    Аватар для maxx™
    Пол
    Мужской
    Адрес
    Одесса
    Возраст
    38
    Сообщений
    23,360
    Репутация
    6089
    Цитата Сообщение от DiMomite Посмотреть сообщение
    Можно еще так делать.
    При этом после добавления нового типа его создание надо прописывать только в одной месте - в фабрике.
    Т.е. получается на с++ в принципе невозможно после создания класса не лезть в код и прописывать ifы?

  7. Вверх #7
    User banned
    Пол
    Мужской
    Сообщений
    2,434
    Репутация
    1159
    Цитата Сообщение от maxx™ Посмотреть сообщение
    Т.е. получается на с++ в принципе невозможно после создания класса не лезть в код и прописывать ifы?
    maxx, все возможно. Иначе не было бы смысла в наследовании и полиморфизме.
    Если у тебя в дочернем классе есть только переопределени(override) и нет замещений(типа, new) - смело объявляй переменную с типом родительского класса и на этапе исполнения присваивай ей экземпляр дочернего - все будет работать гуд.
    Другой вопрос, если были замещения.
    Как самый общий вариант - объявить переменную object и на этапе исполнения делать кастинг, но удобность этого варианта зависит от дальнейшего кода.
    В общем случае, лучше применить интерфейс, и унаследоваться от него тоже.
    Уточни задачу. Может чего придумаем
    Последний раз редактировалось Hose; 03.10.2011 в 11:17.

  8. Вверх #8
    Цитата Сообщение от Hose Посмотреть сообщение
    смело объявляй переменную с типом родительского класса и на этапе исполнения присваивай ей экземпляр дочернего - все будет работать гуд.
    Как я понял сложность как раз в создании дочернего элемента по имени класса в рантайме и состоит.

    В джаве это возможно благодаря рефлексии. Коллеги говорят что в C# как в джаве нельзя. Про С++ тоже больше комментариев что нельзя.
    Один говорит что как-то при помощи макросов можно, хотя у меня это вызывает сомнения - макросы на этапе компиляции разрешаются. Как освободится покажет, если это будет решением, напишу тут.

  9. Вверх #9
    User banned
    Пол
    Мужской
    Сообщений
    2,434
    Репутация
    1159
    Цитата Сообщение от DiMomite Посмотреть сообщение
    Как я понял сложность как раз в создании дочернего элемента по имени класса в рантайме и состоит.

    Коллеги говорят что в C# как в джаве нельзя.
    Давайте коллег в студию. C#, начиная с 2.0 - мая любимая дюльчатай уже не один год

  10. Вверх #10
    Не покидает форум Аватар для Ull9
    Пол
    Мужской
    Адрес
    Мюнхен
    Сообщений
    18,454
    Репутация
    1112
    Записей в дневнике
    1
    class IObjectable
    {
    public:
    IObjectable();
    virtual ~IObjectable() = 0;

    // interface section
    public:
    virtual void execute() = 0;
    };
    одно замечание, насколько я знаю обьявить в базовом классе деструктор чисто виртуальным - не есть гут.
    далее. для явы требуемая функциональноать возможна в силу того что ява - интерпретатор.
    т.е. модули могут компилироватся отдельно. и скажем модуль А, и не знает конкретное имя класса который он вызовет.
    класслоадер этот класс разыщет.

    а в с++ такую штуку легко симитировать используя динамические библиотеки. - но это уже ВНЕ стандарта с++.
    индивидуальная субстанция разумной природы

  11. Вверх #11
    Цитата Сообщение от Ull9 Посмотреть сообщение
    одно замечание, насколько я знаю обьявить в базовом классе деструктор чисто виртуальным - не есть гут.
    Я чуть ниже предоставил пустую реализацию для этого деструктора. Объявление деструктора чисто виртуальным делает класс гарантированно абстрактным (подобного эффекта можно добиться если объявить конструктор protected, тут уже вопрос личных предпочтений). В данном конкретном случае это не обязательно, потому что в классе есть еще одна чисто виртуальная функция. Однако такая "метка", позволяет с первого взгляда определить что класс является абстрактным.

  12. Вверх #12
    Не покидает форум Аватар для Ull9
    Пол
    Мужской
    Адрес
    Мюнхен
    Сообщений
    18,454
    Репутация
    1112
    Записей в дневнике
    1
    первое. абстрактный класс такого понятия в С++ стандарте нет. это вы с явой попутали - там есть.

    далее.. небольшая проблема.
    обьявив деструктор базового класса чисто виртуальным. вы вводите memory leak.
    если вы удаляете обьект используя указатель на базовый класс. у вас происходит потеря памяти.

    нет? я давно кодил в С++.
    индивидуальная субстанция разумной природы

  13. Вверх #13
    Не покидает форум Аватар для Ull9
    Пол
    Мужской
    Адрес
    Мюнхен
    Сообщений
    18,454
    Репутация
    1112
    Записей в дневнике
    1
    Объявление деструктора чисто виртуальным делает класс гарантированно абстрактным (подобного эффекта можно добиться если объявить конструктор protected, тут уже вопрос личных предпочтений).
    тут небольшая путаница.

    конструктор protected, вовсе не гарантирует того что обьект этого типа не может быть создан.
    индивидуальная субстанция разумной природы

  14. Вверх #14
    Цитата Сообщение от Ull9 Посмотреть сообщение
    тут небольшая путаница.

    конструктор protected, вовсе не гарантирует того что обьект этого типа не может быть создан.
    Если в классе с защищенным конструктором друзей задать, то можно создать объект этого класса из класса-друга.
    Из класса-наследника можно защищенный конструктор родителя вызвать.
    А какие еще есть методы ?

  15. Вверх #15
    Цитата Сообщение от Ull9 Посмотреть сообщение
    первое. абстрактный класс такого понятия в С++ стандарте нет. это вы с явой попутали - там есть.
    Абстрактный класс - класс, у которого есть хотя бы одна чисто виртуальная функция. Нет ключевого слова "abstract", термин есть.


    Цитата Сообщение от Ull9 Посмотреть сообщение
    обьявив деструктор базового класса чисто виртуальным. вы вводите memory leak.
    если вы удаляете обьект используя указатель на базовый класс. у вас происходит потеря памяти.
    Это надо проверить, не помню.

  16. Вверх #16
    Не покидает форум Аватар для Ull9
    Пол
    Мужской
    Адрес
    Мюнхен
    Сообщений
    18,454
    Репутация
    1112
    Записей в дневнике
    1
    Цитата Сообщение от DiMomite Посмотреть сообщение
    Если в классе с защищенным конструктором друзей задать, то можно создать объект этого класса из класса-друга.
    Из класса-наследника можно защищенный конструктор родителя вызвать.
    А какие еще есть методы ?
    в классе создать статиц метод, который создаст обьект вызвав хоть protected или privat
    индивидуальная субстанция разумной природы

  17. Вверх #17
    Цитата Сообщение от Ull9 Посмотреть сообщение
    в классе создать статиц метод, который создаст обьект вызвав хоть protected или privat
    Ну это "одиночка". Такое делается осознано и в соответствии с архитектурой. Я подразумевал, что защищенный конструктор либо использование чисто виртуального деструктора защищает от случайных попыток инстанцировать класс.

  18. Вверх #18
    User banned
    Пол
    Мужской
    Сообщений
    2,434
    Репутация
    1159
    Цитата Сообщение от DiMomite Посмотреть сообщение
    А какие еще есть методы ?
    DiMomite, я бы все же не стал искать общие методы, отталкивался бы от конкретной задачи.
    В общем случае, в языке С++ нет и не может быть задач, с требованием создавать экземпляр по имени в рантайм. Есть задачи, когда это могло бы быть удобным, но прожить без этого можно.
    С++ и удобство местами не совсем совместимы
    Для любителей удобств надо как минимум С++/CLI пользовать, а существенно лучше, при возможности сразу в C# или VB.net уходить или в джаву - кто что любит

  19. Вверх #19
    Не покидает форум Аватар для Ull9
    Пол
    Мужской
    Адрес
    Мюнхен
    Сообщений
    18,454
    Репутация
    1112
    Записей в дневнике
    1
    гля дя что понимать под удобством.
    как по мне удобен скальпель. а кто то считает удобным картонный ножик.
    индивидуальная субстанция разумной природы

  20. Вверх #20
    User banned
    Пол
    Мужской
    Сообщений
    2,434
    Репутация
    1159
    Цитата Сообщение от Ull9 Посмотреть сообщение
    гля дя что понимать под удобством.
    как по мне удобен скальпель. а кто то считает удобным картонный ножик.
    Я под удобством понимаю быстроту и эффективность решения современных типовых задач.
    В частности, к решению SaaS архитектур С++ приспособлен боком, с помощью доп.библиотек, тогда как для .net языков и джавы это типовые задачи.
    Конечно, если требуется написать компилятор языка или ОС, подход должен быть индивидуальным, а в решении подавляющего большинства актуальных на сегодня задач гламурные языки вполне оправдывают себя


Ответить в теме
Страница 1 из 2 1 2 ПоследняяПоследняя

Социальные закладки

Социальные закладки

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения