2013-03-19 3 views
0

У меня есть класс типа данных сокета, который используется для чтения и анализа значения из потока сокета (может также использоваться для файла).
Пусть мой класс будет mc_double:Шаблон класса C++ для аналогичных классов

class mc_double { 
    private: 
      double value; 
    public: 
      bool read(socket); 
      write(double); 
} 

Фактический класс является более сложным, но это принцип. Теперь мне нужно разобрать float из потока. Поплавок аналогичен двойному, так что уже реализован int. Не могу ли я объединить определения этого класса со всеми double, int и float как-то шаблоном?

Это то, что я имею в виду:

class mc_<typename = double or int or float> { 
    private: 
      typename value; 
    public: 
      bool read(socket); 
      write(typename); 
}  

Некоторые методы будут затем определены individualy, как mc_double::method() другие будут одинаковыми для всех типов: mc_typename::general_method(). Кроме того, для некоторых я должен был бы только незначительные изменения в коде:

typename mc_typename::return_value() { 
     return val; 
} 

Или конструктор:

mc_typename::mc_typename(<int, long, char, double> number) { 
     val = (typename)number; 
} 

Результат должен быть три классы - mc_int, mc_float и mc_double.
Я нашел официальные документы C++, но я только выяснил последнюю часть моего вопроса - я могу создать функцию, которая принимает несколько типов данных. Остальное, похоже, не так просто.

+1

Я настоятельно рекомендую хорошую книгу на шаблонах C++. – WhozCraig

+0

Целая книга, вероятно, слишком много; однако простой обзор учебника, такой как [этот] (http://www.cplusplus.com/doc/tutorial/templates/), не повредит наверняка. – ulidtko

+0

@ulidtko: Это именно то, что я читал. Это то, что я имел в виду под «официальными документами C++ + C++». –

ответ

3

Вы можете сделать свой класс шаблон класса:

template<typename T, bool base = true> 
class mc { 
protected: 
    T value; 
public: 
    bool read(socket); 
    write(T); 
}; 

Этот класс будет содержать функции-члена, которые являются общими для всех типов T. Тогда вы могли бы специализироваться этот класс шаблоны отдельно для различных типов и пусть они наследуют от mc<T, true>:

template<> 
class mc<double, true> : public mc<double, false> { 
public: 
    // Member functions for double only... 
}; 

template<> 
class mc<int, true> : public mc<int, false> { 
public: 
    // Member functions for int only... 
}; 

Убедитесь, что данные непубличные члены шаблона основного класса сделаны protected, если вы хотите, производные классы доступ к ним.

Вы могли бы создать экземпляр их таким образом:

mc<double> m; 
mc<int> m; 
// ... 

Если вы действительно хотите использовать mc_double и mc_int имена, то вы можете либо:

а) Создание псевдонимов типа для них:

typedef mc<double> mc_double; 
typedef mc<int> mc_int; 

b) Измените дизайн шаблона класса, чтобы не использовать специализацию и иметь один параметр шаблона, и создать вывод г классы самостоятельно:

template<typename T> 
class mc { 
protected: 
    T value; 
public: 
    bool read(socket); 
    write(T); 
}; 

class mc_double : public mc<double> { 
public: 
    // Member functions for double only... 
}; 

class mc_int: public mc<int> { 
public: 
    // Member functions for int only... 
}; 
+0

Спасибо, хотя я ненавижу узнать, что все будет не так просто. Могу ли я спросить вас, что такое 'true' в' '? –

+1

Хорошее использование базового параметра; не думал об этом, чтобы переопределить определенные функции. – Rollie

+0

@ TomášZato: Это просто трюк, который я использую для специализации шаблонов классов, но я признаю, что это не интуитивно. Если вы обнаружите, что это неясно, вы все равно можете использовать второе альтернативное решение в моем ответе, которое проще –

1

Вы можете использовать шаблоны в определении класса следующим образом:

template <typename T> 
class mc 
{ 
public: 
    bool write(T _val); 

private: 
    T mVal; 
}; 

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

class mc_double : public mc<double> 
{ 
public: 
    void doSomethingSpecific() { /* code specific for 'doubles' */ } 
}; 
Смежные вопросы