2014-09-30 4 views
1

(Я прочитал несколько существующих вопросы, касающиеся этого вопроса, и они, кажется, немного отличаются и не делаю вопрос яснее для меня.)Вектора шаблон класса

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

#include <stdio.h> 
#include <string.h> 
#include <vector> 

template <typename T> 
class CCmd 
{ 
    protected: 
     char name[64]; 
     T value; 

    public: 
     CCmd(char* _name, T _value) 
     { 
      strcpy(name, _name); 
      value = _value; 
     } 

     T getValue() 
     { 
      return value; 
     } 

     void setValue(T _value) 
     { 
      value = _value; 
     } 
}; 

int main() 
{ 
    std::vector<CCmd*> vec; 

    vec.push_back(new CCmd<int>("gravity", 150)); 
    vec.push_back(new CCmd<char*>("configfile", "config.cfg")); 

    printf("Value = %d\n", vec[0]->getValue()); 
    printf("Config = %s\n", vec[1]->getValue()); 

    return EXIT_SUCCESS; 
} 

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

... 
class CCmdBase 
{ 
}; 

class CCmd : public CCmdBase 
{ 
... 

и компилятор жалуется что CCmdBase не имеет члена с именем getValue, который, учитывая, что он возвращает общий тип T, будет означать, что базовый класс также должен был быть общим для меня, чтобы определить его там, что означает, что я вернулся туда, где я начал?

Оказание помощи; что мне здесь не хватает?

+0

Вы не очень упускаете из виду. Я полностью сбросил бы геттер и сеттер и вместо этого использовал шаблон посетителя для проверки. –

+0

Поскольку CCmd является классом шаблонов - это не так: «std :: vector »? – Matthias

+1

@ Matthias Да, я написал код, который «логически указал», что мне нужно. – Doddy

ответ

4

Ваш подход нелегко сделать на C++. Скорее всего, ваш дизайн неверен и должен быть улучшен. Трудно дать точный способ, но возможное решение иметь абстрактный базовый класс с чистыми виртуальными функциями. Хотя ваша виртуальная функция не может быть setValue или getValue в вашем текущем «дизайне», поскольку сигнатура функции должна соответствовать виртуальным функциям.

Если вам действительно нужно реализовать подход с различными значениями в векторе, обратите внимание на std::tuple, boost::variant и boost::any. Опять же не ожидайте, что использование такого решения будет легко понятным и понятным для вас.

+0

TBQH, я чувствую, что это один в тех редких случаях, когда дизайн OP не является по своей природе ошибочным, но ограничен спецификой видов в C++.Пожалуйста, поймите: я не говорю это легко, и я не говорю это часто! :) –

2

Это неверно: std::vector<CCmd*> vec;

Вы должны указать тип параметра шаблона. CCmd не является типом, это имя шаблона класса. Например, std::vector< CCmd<int> *> vec;

Невозможно иметь вектор, который непосредственно хранит предметы разных типов. Вектор должен хранить элементы того же типа. Вещь, которую вы ищете, называется гетерогенным контейнером . Стандартного C++ не существует, но вы можете имитировать его с помощью обычного типа, который имеет функции для извлечения «реального» объекта.

Ваша идея std::vector<CCmdBase *> будет работать с использованием полиморфизма во время выполнения. Конечно, вы должны фактически реализовать функции, которые вы хотите в классе CCmdBase. Вы можете иметь функции шаблона внутри определения класса без шаблона, например:

struct CCmdBase 
{ 
    template<typename T> T getValue() 
    { 
     return dynamic_cast< CCmd<T> & >(*this).getValue(); 
    } 

    virtual ~CCmdBase() {} 
}; 
+0

Поскольку вы все равно должны явно указывать тип при вызове 'getValue()' из базового класса, вы также можете использовать статический приведение: 'static_cast const &> (* this) .getValue()'. – davidhigh

+0

@davidhigh OK, хотя это вызывает UB, если вы указали тип неправильно. В этом случае шахта будет делать исключение. –

+0

Вот почему я предложил шаблон посетителя. –

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