2009-07-06 2 views
2

Возможно ли вообще управлять созданием разных классов из конфигураций?Возможно ли создание различных классов, управляемых конфигурациями?

Скажем, у меня есть функция, которая делает это, которое жестко закодировано:

BaseClass* getClassObject(int type) 
{ 
    switch (type) 
    { 
    case 1: 
     return new DerivedClass1(); 
    case 2: 
     return new DerivedClass2(); 
    default: 
     return 0; 
    } 
} 

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

+1

Возможно, вы можете внести ясность в вопрос. В чем проблема с оператором switch? что вам нужно знать типы во время компиляции? вы хотели бы передать ему нечто иное, чем целое число (например, строка с именем класса)? –

ответ

0

Я не гуру C++ - я исхожу из фона Delphi/C#. В Delphi или C# я бы использовал отражение для динамического создания списка возможных классов, а затем выбрать класс, который был настроен в каком-либо файле конфигурации. Однако я не уверен, возможно ли это на C++?

+0

C++ не поддерживает отражение того типа, о котором вы говорите. – 2009-07-06 11:02:07

+0

Ну, тогда это позор ;-) Возьми мой ответ из списка полезных ответов, затем ... –

+0

Или, вы могли бы просто удалить его, прежде чем начинать отмечать его;) –

1

В C++ имена всех типов должны быть известны во время компиляции. Вы не можете позволить пользователю изобретать классы во время выполнения. Однако функция, которую вы отправили, будет работать, - файл конфигурации будет содержать целое число, указывающее, что нужно создать DerivedClass1 или DerivedClass2. Это считывается и используется для выполнения переключения.

+0

Да, вы правы. Само по себе значение «тип» может быть получено из структуры/файла данных конфигурации. – Andy

1

Возможно, вам понадобится Factory method pattern.

+0

Er, функция в моем вопросе - это заводская модель! Я пытаюсь понять, есть ли способ, который не требует записи всего в конкретном. – Andy

+0

Это выглядело как фабричный шаблон, вот почему я разместил эту ссылку. Я не знал, была ли эта модель знакома вам :) –

+0

Не волнуйся. Надеюсь, ты знаешь, что я имею в виду сейчас. – Andy

2

Как Нил, упомянутый в C++, вы не можете изобретать классы во время выполнения.

Возможно, я не понял ваш вопрос правильно, но если вы хотите, чтобы функция/объект вела себя по-разному с предоставленными пользователем данными, вы можете попробовать любое из следующих действий в соответствии с вашими потребностями.

1] Как уже упоминалось в вашем фрагменте кода вы можете использовать любой переключатель или условный оператор (Совершить функцию по-разному на условии пользовательских данных)

или

2] Вы можете использовать заводское шаблон для создания требуется типа объекта (для создания другого объекта в соответствии с пользователем при условии, данные, этот объект может иметь общий базовый класс, чтобы быть сменными в коде, чтобы генерировать различное поведение)

или

3] Вы можете использовать расческу ination of a) функция-создатель, b) наследование и интерфейс c) и загрузка динамической библиотеки для создания и загрузки соответствующего типа объекта во время выполнения. (Это необходимо для загрузки только определенного объекта или функции во время выполнения в соответствии с данными пользователя)

+0

Благодарим вас за ответ. Мне не интересно изобретать классы во время выполнения. Меня интересуют способы сделать код более редактируемым (код будет работать только с существующими классами). – Andy

+0

Еще один способ - использовать функции сценариев вместе с c/C++. Я не уверен, что усилия, необходимые для включения сценариев, оправдывают его выгоду или будут излишним. 1] Вы можете использовать язык TCL с c/C++, который можно использовать с C с минимальными усилиями. или 2] Вы можете создать свой язык сценариев ограниченной функциональности. метод fist будет создавать внешнюю зависимость от TCL, но избавит вас от предоставления синтаксического анализатора и контрольной инструкции. Во-вторых, хорошо, пока вам не нужна ограниченная функциональность, и в будущем вам не понадобится большая экспансия. – nurxb01

1

Из ограниченной информации, предоставленной в вопросе, возможно, вам стоит рассмотреть возможность чтения и/или рассмотрения использования инъекции зависимостей C++ контейнеры.

Это может быть немного тяжело для ваших требований, но это трудно сказать из вопроса. FYI, инъекция зависимостей (http://martinfowler.com/articles/injection.html) - это термин, придуманный Мартином Фаулером, и более конкретный тип инверсии управления (я оставлю вас для дальнейшего изучения обеих тем).

Я лично работал с Castle Windsor, который является контейнером инъекций зависимостей C# /. NET, который позволяет создавать запросы по запрошенным объектам через конфигурационные файлы.

В Википедии есть список контейнеров для инъекций с использованием C++ (http://en.wikipedia.org/wiki/Dependency_injection#Existing_frameworks). Прошло несколько лет с тех пор, как я сделал C++, поэтому я не могу рассказать вам о них больше.

1

Другой альтернативой является использование шаблона прототипа, где часть интерфейса для BaseClass - это функция clone(). Затем вы создаете массив экземпляров прототипов и вызываете клон на них, чтобы получить новый объект. Это полезно, если вы хотите создавать экземпляры, которые различаются по значению, а также те, которые отличаются только поведением, и часто немного меньше работают, чем создавать фабричные методы.

class BaseClass 
{ 
public: 
    virtual BaseClass* clone() const = 0; 
    virtual ~BaseClass() { } 
    virtual void write() const = 0; 
}; 

template <class C> 
class Cloneable : public BaseClass 
{ 
public: 
    virtual BaseClass* clone() const { 
     return new C (*static_cast<const C*> (this)); 
    } 
}; 

class TypeA : public Cloneable<TypeA> 
{ 
    int value; 

public: 
    TypeA (int value) : value (value) { } 

    virtual void write() const { 
     std::cout << "TypeA (" << value << ") @ " << (void*) this << std::endl; 
    } 
}; 

class TypeB : public Cloneable<TypeB> 
{ 
public: 
    TypeB() { } 

    virtual void write() const { 
     std::cout << "TypeB @ " << (void*) this << std::endl; 
    } 
}; 



int main (int argc, char* argv[]) 
{ 
    std::vector<BaseClass*> prototypes; 

    prototypes.push_back (new TypeA (1)); 
    prototypes.push_back (new TypeA (2)); 
    prototypes.push_back (new TypeB); 

    // create some objects 
    std::vector<BaseClass*> instances; 

    for (size_t i (0); i < 8; ++i) 
     instances.push_back (prototypes [ i % 3 ] -> clone()); 

    for (size_t i (0); i < 8; ++i) 
     instances[ i ] -> write(); 

    // todo: delete everything 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^