elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Asignaciones e inicializacion de constructores..
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Asignaciones e inicializacion de constructores..  (Leído 623 veces)
digimikeh

Desconectado Desconectado

Mensajes: 180


Ver Perfil
Asignaciones e inicializacion de constructores..
« en: 22 Junio 2019, 22:05 pm »

Buenas..

Me ha causado extrañeza la forma en que se puede inicializar un tipo a traves de un argumento al constructor:

Código
  1. struct s {
  2. private:
  3. int x = 0;
  4. public:
  5. s(int _x) : x{ _x } {}
  6. void p() const { std::cout << x; }
  7. int getx() const { return x; }
  8. };
  9.  
  10. int main() {
  11. s _s(5);                                       //forma argumento a constructor 1
  12. s _t = 6;                                     //forma argumento a constructor 2
  13. s _u{ 7 };                                   //forma argumento a constructor 3
  14. s _v = { 8 };                              //forma argumento a constructor 4
  15.  
  16. std::cout << std::endl;
  17. std::cout << _s.getx() << std::endl; //salida : 5
  18. std::cout << _t.getx() << std::endl; //salida : 6
  19. std::cout << _u.getx() << std::endl; //salida : 7
  20. std::cout << _v.getx() << std::endl; //salida : 8
  21. return 0;
  22. }
  23.  

Siempre he inicializado un tipo (que reciba un argumento de constructor) con los parentesis, es decir, tal como sale en la salida 5, es decir:
Código
  1. s _s(5);
  2.  


Sin embargo, estaba convencido que la siguiente linea solo tenia como fin la asignacion de un valor:
Código
  1. s _t = 6;
  2.  

Me ha parecido curioso porque se supone que una asignacion por regla general debe tener el mismo tipo que el asignado... sin embargo, el tipo s no es un entero.


Entonces me pregunto si esa linea realmente es una asignacion o lleva otro nombre....





« Última modificación: 22 Junio 2019, 22:07 pm por digimikeh » En línea

Dungeons & dragons;
dragons.Attack();
_TTFH_3500

Desconectado Desconectado

Mensajes: 119



Ver Perfil
Re: Asignaciones e inicializacion de constructores..
« Respuesta #1 en: 22 Junio 2019, 22:29 pm »

C++ crea de forma implicita un contructor por defecto (sin parametros) y sobrecarga el operando de asignacion en el caso de que la clase sea bastante trivial, es decir implementa lo siguiente a partir de tu codigo:

Código
  1. class s {
  2. private:
  3. int x;
  4. public:
  5. s() { x = 0}
  6. s(int x1) { x = x1; }
  7. s operator=(int x1) { x = x1; return *this; }
  8. void p() const { std::cout << x; }
  9. int getx() const { return x; }
  10. };

La linea s t = 6; en el main llama al constructor por defecto s() y pone x = 0, luego llama s.operator=(6) y pone x = 6

Otra cosa que no tiene que ver con tu pregunta, NUNCA pongas uno o dos guion bajo al principio del nombre de una variable en C++, esos nombres estan reservados para las librerias del lenguaje y es una mala practica de programacion que deriva de los lenguajes no case-sensitive como Visual Basic donde para diferenciar User y user escribes _user.

Citar
"Don't overlegislate naming, but do use a consistent naming convention: There are only two must-dos: a) never use "underhanded names," ones that begin with an underscore or that contain a double underscore;" (p2 , C++ Coding Standards, Herb Sutter and Andrei Alexandrescu)



En línea

digimikeh

Desconectado Desconectado

Mensajes: 180


Ver Perfil
Re: Asignaciones e inicializacion de constructores..
« Respuesta #2 en: 22 Junio 2019, 23:15 pm »

Hola, tendre en cuenta esa convención de las variables, gracias.
puede ser de la siguiente forma?:

Código
  1. int un_numero = 6;
  2.  

o es mejor asi? :

Código
  1. int unNumero = 6;
  2.  


Respecto a la autoasignacion del operador =, C++ lo hara para todos los tipos creados por el usuario que no haya recargado el operador = ? o tiene distinciones ?..

Saludos y gracias.

« Última modificación: 22 Junio 2019, 23:18 pm por digimikeh » En línea

Dungeons & dragons;
dragons.Attack();
@XSStringManolo
<svg/onload=alert()>
Colaborador
***
Desconectado Desconectado

Mensajes: 2.229


Turn off the red ligth


Ver Perfil WWW
Re: Asignaciones e inicializacion de constructores..
« Respuesta #3 en: 23 Junio 2019, 00:59 am »

Hay formas de nombrar a la variables que suelen prevalecer, y en algunas librerías, en la documentación prácticamente te fuerzan a su manera.

Es mejor la segunda opción.
Por qué?
Porque alguna librerías suelen usar el guion bajo para separar el tipo del dato del nombre de la variable.

El un_numero se podría interpretar como una variable unsigned int. Mucho lo entederan como UnsignedNumberNumero.

En algunas librerías se nombran de esa manera, por ejemplo p_Numero lo entenderan como un puntero.

Librerías como la windows api usan la inicial para describir el tipo de variable. Por ejemplo nVariable se entiende como una variable que contiene un número. hVentana es un handler a una ventana. Etc.

A mi me gusta usar variables que empiecen en minúsculas con nombres largos que describan mejor lo que almacenan. Para las funciones uso la primera mayúscula. Para defines uso todo mayúsculas.

Asi si lees en mi codigo:
funcion variable
Funcion funcion
FUNCION macro

Sabes que siempre uso el mismo método y puedes saber que es.
En caso de sobrecargar funciones para que devuelvan datos distintos con el mismo nombre uso:
n_Funcion numero
c_Funcion caracter
s_Funcion string
...

No es importante que método uses, lo importante es que no lo cambies durante todo el código y siempre respetes esa norma a rajatabla.

Yo suelo poner nombres largos del estilo:
unsigned short int numeroDeCaracteresQueContieneElArrayescenario;
Podrias usar la abreviatura y añadir un comentario.
unsigned short int n_soae; //Size of Array escenario

Con esta forma de nombrar las variables puedes acordarte facilmente palabras largas que comentaste en la declaración de la variable:
noeiaoslistaDeAdmitidos
number of elements inside array of strings "listaDeAdmitidos".

Desde luego es preferible a llamarle a las variables a, b, c, d...
Imaginate que en la linea 4582 del código declaraste:
int a;
char b;

en la línea 4800 del código:
string c;
Mivector d {4, a};

En la linea 5430 del codigo:
string e = "ejemplo";

En la línea 6323:
string f = e;
//operaciones
Código
  1. if (operacion1 == operacion2)
  2. {
  3. e = f;
  4. }
  5.  
  6. Y en la línea 7214 tienes:
  7. if (a<=b || e.size() <= a && f.size() != 2 )
  8. {
  9.   for (int i = 3; i < e.size() || i != f.size() +a ; ++i)
  10.   {
  11.   i = a;
  12.   ++a;
  13.    e.append(f, a,( e*e.size())-a));
  14.      while (!e.empty())
  15.      {
  16.       for (auto iter ....
  17.       {
  18.         f.append(*iter);
  19.        e.resize((e.size()-1));
  20.        }
  21.       }
  22.    }
  23. }
  24.  
Vas a tener que andar a buscar por el codigo 200 veces paea entender una funcion.
Podrias ahorrar todo ese sufrimiento al lector de codigo con un simple comentario de 2 lineas y usar nombres que representen mejor que tiene cada cosa:
/*
Este codigo llena el vectorNombresDeAlumnos del tipo creado MiVector vector<inicialesDeAlumnos>
Si el string sColegio no ha sido modificado previamente. */
« Última modificación: 23 Junio 2019, 01:04 am por string Manolo » En línea

_TTFH_3500

Desconectado Desconectado

Mensajes: 119



Ver Perfil
Re: Asignaciones e inicializacion de constructores..
« Respuesta #4 en: 23 Junio 2019, 01:13 am »

Puedes usar guion bajo siempre que no este al comienzo o hallan dos seguidos.
MAL:
int _numero;
int un__numero;
int __ARRAY_
BIEN:
int un_numero;
int esto_es_una_variable;
int estoTambien;

C++ implementa los siguientes metodos... a veces, no estoy seguro de cuando, depende de si una clase hereda de otra, es virtual o virtual pura, usa un template, etc. Igual no importa mucho, si lo usas y te da error al compilar entonces no esta definido y tienes que implementarlo vos, si te da error en la ejecucion quizas lo implemento y no hace lo que quieres y tienes que redefinirlo*.

Código
  1. class array {
  2. private:
  3.  int inicio, tamanio;
  4.  int* datos;
  5. public:
  6.  // Constructor por defecto (sin parametros):
  7.  array();
  8.  // Constructor por copia
  9.  array(const array&);
  10.  // Constructor por movimiento
  11.  array(array&&);
  12.  // Operador de asignacion
  13.  array operator=(const array&);
  14.  // Operador de asignacion por movimiento
  15.  array& operator=(array&&);
  16.  // Destructor
  17.  ~array();
  18.  
  19.  // NO implementa otros constructores
  20.  array(int, int, int*);
  21.  // NO implementa la comparacion
  22.  bool operator==(const array&);
  23.  bool operator<=(const array&);
  24. };
  25.  

*
Código
  1. // Lo que hace por defecto
  2. array::array(const array& arr) {
  3.  start = arr.start;
  4.  size = arr.size;
  5.  data = arr.data;
  6. }
  7.  
  8. // Lo que tu quieres que haga
  9. array::array(const array& arr) {
  10.  start = arr.start;
  11.  size = arr.size;
  12.  data = new int[size];
  13.  for (int32_t i = 0; i < size; i++)
  14.    data[i] = arr.data[i];
  15. }
  16.  

En línea

RayR

Desconectado Desconectado

Mensajes: 127


Ver Perfil
Re: Asignaciones e inicializacion de constructores..
« Respuesta #5 en: 23 Junio 2019, 01:57 am »

En el caso del código que pusiste, en esta línea:

Código
  1. s _t = 6;
  2.  

en realidad no se invoca al constructor por defecto ni al operator=. De hecho, dando  que tú ya escribiste un constructor, el compilador ya no genera la versión por defecto o sin parámetros (sólo la genera si tú no creas ninguno, o si se lo pides, con  = default). Y por supuesto, en ningún caso generaría una sobrecarga de operator= que tome como parámetro un int. El único operador de asignación que el compilador generará automáticamente toma como parámetro una referencia const (en algunos casos, no const) al mismo tipo de la clase, en este caso s.

Lo que en realidad sucede en esa línea es que se invoca al constructor que tú definiste, y se le pasa como parámetro 6. O sea, es equivalente a esto:

Código
  1. s _t(6);
  2.  

En cuanto a tu última pregunta, en general, el compilador genera un operador de asignación para cualquier tipo que crees, salvo unas pocas excepciones (por ejemplo, si contiene alguna variable miembro no static que sea const, o referencia)
En línea

Loretz

Desconectado Desconectado

Mensajes: 108


Ver Perfil
Re: Asignaciones e inicializacion de constructores..
« Respuesta #6 en: 23 Junio 2019, 02:25 am »

Código:
struct s {
private:
int x = 0;
public:
s(int _x) : x{ _x } {}              //  converting constructor: inicializa un s a partir de un int
void p() const { std::cout << x; }
int getx() const { return x; }
};

Estas cuatro expresiones hacen exactamente lo mismo: invocan al "converting constructor".
Código:
s _s(5);      // crea _s a partir del int 5   
s _t = 6;      // crea _t a partir del int 6
s _u{ 7 };     // crea _u a partir del int 7 (direct-list-initialization a partir de C++11)
s _v = { 8 }; // crea _v a partir del int 8 (copy-list-initialization a partir de C++11)

En este caso las cuatro expresiones construyen e inicializan un objeto de tipo 's' a través del "converting constructor", que es el constructor que especifica la conversión desde el tipo int al tipo s.

En C++98 sólo existían las dos primeras y C++11 introduce las dos últimas, que las llama "uniform initialization", en sus dos variantes, "direct list initialization" y "copy list initialization".

Si observas la salida del programa, se mostrarán los ints 5, 6, 7, y 8 porque esos son los valores con que cada objeto fue inicializado.

Y Si usas el debugger para ejecutar paso a paso el programa, verás que cómo el flujo de ejecución pasa por ese constructor.
En línea

digimikeh

Desconectado Desconectado

Mensajes: 180


Ver Perfil
Re: Asignaciones e inicializacion de constructores..
« Respuesta #7 en: 23 Junio 2019, 06:00 am »

Entiendo, ya me va quedando todo mas claro... gracias por las respuestas..

Vaya Stroustup, que le gusta complicar las cosas, pero supongo que es para mejor...
En línea

Dungeons & dragons;
dragons.Attack();
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Conflicto con asignaciones de variables
Programación Visual Basic
demoniox12 6 1,137 Último mensaje 10 Septiembre 2008, 23:14 pm
por demoniox12
PIC C inicializacion
Programación C/C++
crema3000 1 1,154 Último mensaje 8 Septiembre 2010, 16:15 pm
por Debci
Clase Derivada; Listas de Inicializacion.
Programación C/C++
necro1991 2 3,324 Último mensaje 11 Octubre 2010, 05:45 am
por necro1991
inicializacion de apuntador
Programación C/C++
valentz 2 632 Último mensaje 9 Abril 2019, 22:11 pm
por laephy
iteratores de flujo....inicializacion de vector, etc.
Programación C/C++
digimikeh 4 874 Último mensaje 3 Agosto 2019, 04:40 am
por digimikeh
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines