Problem.
C2440 error: 'initializing': can not convert from
You have not put the complete error nor indicated on which line the error leaps, so we can only make conjectures. A quick error search reveals that you are using MSVC to compile and you could have one of the following errors :
Initialize a char*
or% co_of non-constant% using a string literal.
Try converting a pointer to member to pointer to wchar_t*
.
Try to fully use a class declared but not defined.
Incorrectly using a user-defined conversion.
Other specific incorrect uses of MSVC.
Without knowing more details, I bet your failure is 3 or 4, because in the code:
if (tip.name() == "Objeto") {
Datos1 d1= a.getDatos();
}else if(tip.name() == "Objeto1"){
Datos2 d2=a.getDatos();
}
You are using the types void
and Datos1
, if you do not define both types or if you do not define how the return of Datos2
can be converted to both types then you will have this problem that you describe.
But it is impossible to know for sure without seeing more code. With the code that you have published, you can see that you have an approximation to the serialization that is not considered a good practice in some areas. In addition to relying on type introspection using the implementation dependent operator a.getDatos()
your implementation skips the principles of encapsulation .
Type introspection or Run-time type information (RTTI in English) has significant runtime costs, and evaluating an expression with typeid
can also incur runtime costs .
Exposing externally to your class's data can be considered a design antipattron if it is done without necessity. I assume that after serializing the data you will want to deserialize them so if you expose methods to read internal data you will also need methods to write them.
Your question.
Is it possible to access the members of an object defined as a parameter in a generic function?
It is possible, as long as the members are visible and public or the function is a friend of the object; the type of function does not change this fact:
struct S { int miembro; };
class C { int miembro; };
void guardarDatos(const S &s)
{
std::cout << "vamos a guardar S: " << s.miembro << '\n';
...
}
void guardarDatos(const C &c)
{
// Error, C::miembro es privado
std::cout << "vamos a guardar C: " << c.miembro << '\n';
...
}
template <typename T>
void guardarDatos_plantilla(const T &t)
{
std::cout << "vamos a guardar T: " << t.miembro << '\n';
...
}
S s; C c;
guardarDatos_plantilla(s);
guardarDatos_plantilla(c); // Error, C::miembro es privado
class C2
{
int miembro;
template <typename T>
friend void guardarDatos_plantilla(const T&);
friend void guardarDatos(const C2 &);
};
In the previous example, the functions typeid
or guardarDatos_plantilla
(overload with guardarDatos
) will not have problems accessing C2
despite being private since they are friendly functions of C2::miembro
.
Proposal.
Delegate the serialization and deserialization routines to the objects instead of creating an external class for these purposes.
My approach would be that each object had the ability to serialize itself, either by writing directly to the file or by returning a binary version of its data and status. In parallel, each object should have the ability to deserialize itself, either reading directly from a file or reading binary data:
class SerializableEnArchivo
{
int miembro;
void serializar(std::ofstream archivo)
{
archivo << miembro;
}
void deserializar(std::ifstream archivo)
{
archivo >> miembro;
}
};
using byte_buffer = std::vector<std::uint8_t>;
class SerializableEnBufer
{
int miembro;
byte_buffer serializar()
{
byte_buffer datos{sizeof(miembro)};
// serializar
return datos;
}
void deserializar(const byte_buffer &datos)
{
// deserializar
}
};
You can create an interface based on these ideas and inherit from the interface, but you should think if that is convenient for you:
struct Serializable
{
using byte_buffer = std::vector<std::uint8_t>;
virtual byte_buffer serializar() = 0;
virtual void deserializar(const byte_buffer &) = 0;
};
class Clase : public Serializable { ... };