2012-02-21 78 views
5

Me gustaría crear una clase que tenga una función que guarde los datos enviados a ella, en un archivo de texto. Los datos que se puede pasar a él puede ser cualquier cosa como un std::string, int, double, float, unsigned int, etc., y también puede ser una: std::vector<T>, T[] y std::vector<std::vector<T>>, T[][].Función de plantilla C++ para matrices, vectores, tipos incorporados, STL

Ahora, obviamente, si se trata de una matriz, tendré que repetirla para enviar los datos a un archivo de texto.

Estaba pensando en usar plantillas, pero no estoy seguro de cómo hacer las matrices.

¿Es este el camino a seguir?

class CMyClass 
{ 
    template<typename T> 
    void SaveData(T data); 
    void SaveData(std::vector<T> data); 
    void SaveData(std::string data); 
    void SaveData(T* data);    // Perhaps I'll also need to pass in the size. 
    void SaveData(std::vector<std::vector<T>> data); 
    void SaveData(T** data); 
}; 

Me imagino que el código para el std::string sería el mismo que el código de la std::vector<T> siempre que T es construido en un tipo (como un int o float o algo así).

Y luego escribo las funciones para cada uno de los SaveData(...) en consecuencia?

+0

Su título es muy amplio y vago, es posible que desee volver a expresarlo. –

+4

FYI: http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/index.html – Anycorn

Respuesta

5

En primer lugar, se puede o bien la plantilla de la clase o las funciones. Como también desea hacer arreglos, debe ir con la última opción.Ejemplo es el siguiente:

class CMyClass 
{ 
public: 
    template<typename T> void SaveData(const T &data); 
    template<typename T, size_t N> void SaveData(const T (&data)[N]); 
    template<typename T, size_t N, size_t M> void SaveData(const T (&data)[N][M]); 
    template<typename T> void SaveData(const std::vector<T> &data); 
    template<typename T> void SaveData(const std::vector<std::vector<T> > &data); 
    void SaveData(const std::string &data); 
}; 

Una vez definidas las funciones, el siguiente ejemplo muestra cómo se les puede llamar:

int i; 
int i1[5]; 
int i2[5][7]; 
std::vector<int> v1; 
std::vector<std::vector<int> > v2; 
std::string s; 

CMyClass saveClass; 

saveClass.SaveData<int>(i); 
saveClass.SaveData<int>(i1); 
saveClass.SaveData<int>(i2); 
saveClass.SaveData<int>(v1); 
saveClass.SaveData<int>(v2); 
saveClass.SaveData(s); 

Dependiendo de sus necesidades, usted podría hacer la clase de un producto único y de las funciones estáticas , omitiendo la necesidad de crear instancias de CMyClass en absoluto y simplemente llamando a las funciones de la siguiente manera:

CMyClass::SaveData<int>(i); 
CMyClass::SaveData<int>(i1); 
CMyClass::SaveData<int>(i2); 
CMyClass::SaveData<int>(v1); 
CMyClass::SaveData<int>(v2); 
CMyClass::SaveData(s); 

Notas:

  1. Los argumentos también deben ser referencias (es decir "& datos" en lugar de "datos"), por lo que solo se pasa la referencia en lugar de realizar una copia de todo el contenedor cada vez que llame a la función.
  2. He declarado explícitamente las funciones como públicas, suponiendo que esta sea la clase completa y sus funciones serán accedidas por otra clase. Por defecto, los miembros de una clase son privados.
  3. Asegúrese de que haya un espacio entre cada ">" anidado.

¡Buena suerte!

+0

¡Muchas gracias! Eso realmente ayuda. Sin embargo, tengo una pregunta: ¿por qué usaste la palabra matriz en lugar de datos? ¿Es solo un nombre, o ... hace algo, porque leo que solo en VS hace algo? –

+0

Mi uso de "matriz" como el nombre de la variable era solo una fuerza de hábito. He editado el código para que ahora sea "datos" para mantener la coherencia de la interfaz. No se preocupe, "array" no es una palabra clave en C++. Perdón por cualquier confusión que pueda haber causado! – athwaites

+0

Gracias, una última pregunta, para implementar std :: vector >, tendría que hacer una sobrecarga separada de nuevo, no lo haría, a pesar de que el método sería el mismo que el de std :: vector >? –

0

Creo que estás mezclando dos cosas en una clase, lo cual se debe evitar: por lo que puedo ver, de lo que se trata tu clase (su "responsabilidad") es escribir datos en un archivo. Otra cosa que está agregando es conocimiento sobre la iteración de colecciones de datos.

Tome un vistazo a <algorithm> métodos de STL:

http://www.cplusplus.com/reference/algorithm/

Allí se pueden encontrar formas genéricas de los datos de iteración, por ejemplo, en el find método:

template<class InputIterator, class T> 
    InputIterator find (InputIterator first, InputIterator last, const T& value) 
    { 
    for (;first!=last; first++) if (*first==value) break; 
    return first; 
    } 

Esto le hace independiente de si se está utilizando vector, list, matrices o lo que sea.

Si también desea serializar cosas como vector<vector<T> > (tenga en cuenta el espacio entre los dos >!), Tiene que explicar más sobre lo que quiere hacer con esos datos. Simplemente concat los elementos como si todos T s estuvieran en uno vector? En este caso, puede tratar de crear un nuevo iterador que haga exactamente esto.

El impulso biblioteca iterador podría ayudar con esto:

http://www.boost.org/doc/libs/1_48_0/libs/iterator/doc/index.html

+0

Gracias por la sugerencia. Para más detalles, me gustaría escribir todo lo que se transfiere, a un archivo de texto de esta manera: ifstream ifs ("test.txt", ifstream :: in); ifs << datos. Si los datos son un vector , entonces tengo que iterar sobre él, si los datos son un int, entonces no. Si los datos son un T [] [] entonces también tengo que iterar sobre eso ... Conozco el algoritmo std :: y funciones como for_each (...); sin embargo, no veo cómo ayudarían si el usuario transfiere un int o un char. Además, no creo que pueda usar std :: for_each para cosas como std :: vector >. –

Cuestiones relacionadas