C ++ универсальные классы и наследование - PullRequest
1 голос
/ 14 ноября 2009

Я новичок в общем программировании классов, так что, возможно, мой вопрос глупый - извините за это. Я хотел бы знать, возможно ли следующее, и если да, то как это сделать

У меня есть простой универсальный класс Provider, который предоставляет значения универсального типа:

template <class A_Type> class Provider{
public:
A_Type getValue();
    void setSubProvider(ISubProvider* subProvider)
private:
A_Type m_value;
ISubProvider* m_subProvider;
};

Функция getValue должна возвращать m_value, если m_subProvider равен NULL. Но если SubProvider не равен Null, значение должно быть рассчитано классом SubProvider.

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

template <class A_Type> class ISubProvider{
public:
virtual A_Type getValue() = 0;
};

теперь я хочу, чтобы фактические реализации ISubProvider были неуниверсальными! например, я хочу реализовать IntegerProvider, который возвращает тип Integer

class IntegerProvider : public ISubProvider{
   int getValue(){return 123;}
};

и, возможно, StringProvider:

class StringProvider : public ISubProvider{
  string getValue(){return "asdf";}
};

Теперь - как мне все это кодировать, чтобы я мог использовать

void setSubProvider(ISubProvider* subProvider)

Функция класса Provider только с субпоставщиком, который соответствует универсальному типу Provider?

например, если я создаю провайдера типа int:

Provider<int> myProvider = new Provider<int>();

тогда можно будет позвонить

myProvider.setSubProvider(new IntegerProvider());

но нельзя звонить

myProvider.setSubProvider(new StringProvider());

Надеюсь, вы понимаете мой вопрос и можете сказать, как правильно создать этот код:)

Спасибо!

Ответы [ 3 ]

3 голосов
/ 14 ноября 2009

C ++ имеет шаблоны (шаблоны классов и шаблоны функций), а не шаблоны.

Учитывая это объявление:

template <class A_Type> class ISubProvider;

вы не можете сделать это:

class IntegerProvider : public ISubProvider{
    int getValue(){return 123;}
};

потому что ISubProvider - это не класс, это шаблон класса.

Вы можете сделать это.

class IntegerProvider : public ISubProvider<int> {
    int getValue(){return 123;}
};

Я думаю, что это то, что вы хотите сделать, в любом случае.

Это также не будет работать по той же причине.

template <class A_Type> class Provider {
public:
    A_Type getValue();
    void setSubProvider(ISubProvider* subProvider)
private:
    A_Type m_value;
    ISubProvider* m_subProvider;
};

Вы должны сделать что-то подобное.

template <class A_Type> class Provider {
public:
    A_Type getValue();
    void setSubProvider(ISubProvider<A_Type>* subProvider);
private:
    A_Type m_value;
    ISubProvider<A_Type>* m_subProvider;
};

Теперь вы достигли того, что хотели, в том, что вы должны предоставить указатель на экземпляр ISubProvider для того же параметра типа шаблона, что и для шаблона класса Provider.

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

1 голос
/ 14 ноября 2009

Вы должны извлечь из вашего ISubProvider следующим образом

class IntegerProvider : public ISubProvider<int>
class StringProvider : public ISubProvider<string>

и т. Д.

Также измените объявление класса

template <class A_Type> class Provider{
public:
A_Type getValue();
    void setSubProvider(ISubProvider<A_Type>* subProvider)
private:
A_Type m_value;
ISubProvider<A_Type>* m_subProvider;
};
0 голосов
/ 14 ноября 2009

Если вы отбросите отдельную идею провайдера / суб-провайдера и просто создадите одного провайдера, ваша проблема решится сама собой.

template <class A_Type> class Provider{
  typedef Provider< A_Type > my_type;

public:
  A_Type getValue();
  void setSubProvider(my_type* subProvider)
private:
  A_Type m_value;
  my_type* m_subProvider;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...