2013-05-30 6 views
1

У меня проблема с небольшой частью кода, я пытаюсь работать с шаблонами и вектором класса шаблонов
Друг помог мне со следующим кодом, доведя его до состояния, в котором он компилируется, но я до сих пор не могу использовать производные классов достаточно хорошо, так что я полностью потерянным, и я не могу пройти мимо этой маленькой ошибки, я мог бы реально использовать вашу помощьВектор шаблонного класса?

#include <iostream> 
    #include <vector> 

    class data_base 
    { 
    public: 
     data_base(std::string &_id); 

     std::string id; 
    }; 

    template <typename T> 
    class data : public data_base 
    { 
    public: 
     data<T>(T &_data, std::string &_id); 

     T *data; 
    }; 

    data_base::data_base(std::string &_id) 
    { 
     id = _id; 
    } 

    template <typename T> 
    data<T>::data(T &_data, std::string &_id) 
    { 
     data =& _data; 
     id = _id; 
    } 


    int main() 
    { 
     std::vector< data_base*> stuff; 

     return 0; 
    } 

Как бы один обойдите с использованием данных класс и положить его в вектор материала, и получить доступ к нему позже?
Да, и если кто-нибудь знает хороший учебник об использовании базовых/производных классов, я мог бы реально использовать, что
Заранее спасибо

+2

'data_base' кажется совершенно бесполезным, поскольку он не имеет виртуальных функций. Вы пытаетесь повторно внедрить 'boost :: any'? –

+0

Я использую часть этого кода, в старой версии моего кода сериализации, я недавно решил изменить его на совместимость с шаблонами, но я не могу заставить его работать. Есть ли способ полностью игнорировать базовый/производный класс и просто перейти к одному шаблону вектора классов любым возможным способом? –

ответ

2

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

Это на самом деле довольно просто. Давайте проведем несколько шагов.

Чтобы создать один экземпляр вашего шаблонного класса данных, вы объявите его с типом вы хотите его использовать в угловых скобках:

data<int> MyDataObject(0, "zero"); 

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

Чтобы объявить вектор типов, вы указываете тип внутри угловых скобок вектора, как вы уже знаете. Итак, попробуйте это теперь вы знаете, как объявить версию своего класса с использованием определенного типа данных:

std::vector<data<int>> MyVector; 

ли вы видите логику?

Однако есть уловка: это не будет компилироваться на большинстве компиляторов C++, но это не потому, что вы допустили логическую ошибку. Это потому, что >> в конце не распознается как часть объявления типа - это рассматривается как нечто другое (>> имеет другое значение. Я считаю, что эта проблема в этой ситуации исправлена ​​в последней спецификации на C++.) Чтобы исправить это, заставить компилятор правильно разобрать его, добавив пробел:

std::vector<data<int> > MyVector; 

Пробелы обычно не имеет значения для исходного кода компилятор разборе, но здесь он делает.

Теперь у вас есть вектор вашего класса данных с использованием ints.

Чтобы ознакомиться с использованием векторов, я рекомендую this page as a good reference. Но краткий обзор состоит в том, что вы используете push_back() для добавления элемента к вектору и можете использовать индексацию массива, то есть [], для доступа к определенному элементу по индексу, начиная с 0 для первого элемента и используя size(), чтобы узнать, сколько элементы он содержит:

data<int> MyDataObject(0, "zero"); 
MyVector.push_back(MyDataObject); 

data<int> Test = MyVector[0]; // Gets the first item - since only one was added, it should equal MyDataObject. 

Обратите внимание, что MyDataObject и MyVector оба выделяются в стеке, так что они будут уничтожены, когда они выходят из области видимости (метода или блока, где каждый объявлен - блок-является {...} раздела - end.) Вы также можете выделить в куче и сохранить указатели на базовые объекты в векторе. Если вы хотите знать, как это сделать, прокомментируйте, я могу расширить ответ.

Да, и если кто-нибудь знает хороший учебник об использовании базовых/производных классов, я мог бы реально использовать, что

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

Но здесь есть одна очевидная ошибка. Ваш код данных (производный класс) имеет этот конструктор:

template <typename T> 
    data<T>::data(T &_data, std::string &_id) 
    { 
     data =& _data; 
     id = _id; 
    } 

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

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

template <typename T> 
data<T>::data(T &_data, std::string &_id) : 
    data_base(id) // call parent constructor 
{ 
    data =& _data; 
} 

Элементы, которые появляются после: в конструкторе, являются «списком инициализации». Фактически, вы можете все там положить:

template <typename T> 
data<T>::data(T &_data, std::string &_id) : 
    data_base(id), // call parent constructor 
    data(_data) 
{ } 

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

template <typename T> 
data<T>::data(T &data, std::string &id) : 
    data_base(id), // call parent constructor 
    m_data(data) 
{ } 

и изменения объявление должно соответствовать (и аналогичным образом изменить базовый класс.) Попробуйте назвать вещи, чтобы вы могли различать типы, локальные переменные и переменные-члены как минимум.

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