template<class T>class stack_element
{
protected:
stack_element<T> * prev;
public:
T content;
};
С++ Создание массива объектов шаблонного класса; указатель на шаблонный объект стека
Есть шаблонный класс template<class T>class human, а также пораждённые от него классы, например template<class T>class emploee : public human<T>
Как можно создать массив, который мог бы хранить объекты этих классов с разными типами, например human<int> и human<char *>?
Для простых объектов сработал бы human * aray[4];, но не для шаблонных.
Кроме того есть класс стека с шаблонным содержанием
Код:
Как реализовать указатель, который может хранить адреса на объекты стека с разными типами данных. Например если у нас в первом объекте int, а во втором char, то второй должен содержать указатель на первый, который имеет тип данных int, а не char, как этот. Естественно данная конструкция нерабочая.
Или если это невозможно, то как можно по-другому связать стек с шаблоными данными?
Код:
struct people
{
virtual ~people(){}
};
template<class T>
class human: public people
{
};
template<class T>
class emploee : public human<T>
{
};
human<int>* aray[4];
int main()
{
human<int> hi;
human<double> hd;
emploee<int> ei;
people* pp[3];
pp[0] = &hi;
pp[1] = &hd;
pp[2] = &ei;
return 0;
}
{
virtual ~people(){}
};
template<class T>
class human: public people
{
};
template<class T>
class emploee : public human<T>
{
};
human<int>* aray[4];
int main()
{
human<int> hi;
human<double> hd;
emploee<int> ei;
people* pp[3];
pp[0] = &hi;
pp[1] = &hd;
pp[2] = &ei;
return 0;
}
Надо эти объекты из массива сохранять в файл
Код:
ofstream wfilez("emploees1.save");
wfilez.write((char *) pp[1], sizeof(people));
wfilez.write((char *) pp[1], sizeof(people));
не работает, опять вместо people нужно указывать конкретный объект и его тип, например wfilez.write((char *) pp[1], sizeof(human<double>)) работает, но это естественно неприемлимо.
Можно писать в файл отдельно все переменные объекта, но тут проблема в другом:
Код:
template<class T>class human : public mammals
{
public:
human(T, char *, char *, int); //инициализация параметров
virtual void show_info(void); //показыввает параметры
virtual void save(void); // сохраняет объект в файл
//bool FileExist(const char*); //проверяет файл на существование
// friend class body;
protected:
T ID;
char name[32];
char name2[32];
int age;
template<class T>human<T>::human(T id ,char *name, char *name2, int age)
{
ID = id;
strcpy(human::name, name);
strcpy(human::name2, name2);
human::age = age;
}
};
{
public:
human(T, char *, char *, int); //инициализация параметров
virtual void show_info(void); //показыввает параметры
virtual void save(void); // сохраняет объект в файл
//bool FileExist(const char*); //проверяет файл на существование
// friend class body;
protected:
T ID;
char name[32];
char name2[32];
int age;
template<class T>human<T>::human(T id ,char *name, char *name2, int age)
{
ID = id;
strcpy(human::name, name);
strcpy(human::name2, name2);
human::age = age;
}
};
Тут всё хорошо, но до тех пор, пока T не char. И если он чар, то во-первых он char *, чтобы можно было присвоить как обычную переменную в конструкторе. И вот когда её надо записать в файл, то
wfile.write((char *) &ID, sizeof(T)); уже не сработает хотя бы потому, что sizeof(T) нужно умножить длинну строки.
Так что вот и вопрос: либо как целиком записывать объекты из массива, либо как реализовать корректно запись шаблонной переменной.
Кроме того потом еще из файла надо будет делать загрузку и как определить тип данных, записанный из шаблонной переменной и потом на основании этих данных создавать объект с соответствующим типом для загрузки - тоже вопрос.
Цитата: Frenzyk
Можно писать в файл отдельно все переменные объекта, но тут проблема в другом...
Во первых проблема в смешении разных стилей программирования. Непонятно почему не использовать строки string из STL, если уж используются потоки?
Абстрактный класс родитель может содержать функцию со ссылкой на файловый поток, в который и будет писать данные. Что-то типа
virtual void Write(ofstream &f) = 0;
В наследниках эта функция будет заменяться но нужную типа
virtual void Write(ofstream &f){f << _val1 << _val2 << _val3 << ...; }
С чтением хуже - придется выдумывать какой-то формат записи для разных типов и парсер, который будет генерить соответствующие объекты.
Да, я так примерно и сделал, но одно дело, когда _val1 - это просто переменная(int, float) и другое, когда это массив символов char(т.к. это шаблоннная переменная, то она может быть и тем и другим), точнее в моём случае указатель char * - нужен какой-то универсальный алгоритм, чтоб записывал и простые переменные и то, что находится по указателю на строку символов, или массив символов.
Цитата: Frenzyk
Да, я так примерно и сделал, но одно дело, когда _val1 - это просто переменная(int, float) и другое, когда это массив символов char
В том то и дело, что примерно...
Ну да ладно, можно и по другому подойти, если использовать специализацию шаблонов функций. Примерно так:
Код:
template<class T> void Save(ofstream &f, T v)
{
f.write(reinterpret_cast<char*>(&v), sizeof(v));
}
template<> void Save<const char*>(ofstream &f, const char* v)
{
f.write(v, strlen(v));
}
template<class T>
class classA
{
T _val;
// ... другие параметры
public:
void SetVal(const T &v){_val = v;}
classA(T v):_val(v){}
void Write(ofstream &f){Save(f, _val); /* ... */ }
};
int main()
{
classA<const char*> a("testA\r\n");
classA<int> b(567);
classA<const char*> c("\r\ntestC");
ofstream w("test.txt");
a.Write(w);
b.Write(w);
c.Write(w);
return 0;
}
{
f.write(reinterpret_cast<char*>(&v), sizeof(v));
}
template<> void Save<const char*>(ofstream &f, const char* v)
{
f.write(v, strlen(v));
}
template<class T>
class classA
{
T _val;
// ... другие параметры
public:
void SetVal(const T &v){_val = v;}
classA(T v):_val(v){}
void Write(ofstream &f){Save(f, _val); /* ... */ }
};
int main()
{
classA<const char*> a("testA\r\n");
classA<int> b(567);
classA<const char*> c("\r\ntestC");
ofstream w("test.txt");
a.Write(w);
b.Write(w);
c.Write(w);
return 0;
}