Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
highlevel:c:xtra [2008/05/27 10:48] alfred |
highlevel:c:xtra [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| - | ====== Xtra ====== | + | ====== C\C++ Xtra ====== |
| ===== Lenguaje ===== | ===== Lenguaje ===== | ||
| Línea 12: | Línea 12: | ||
| * ''\"'', comillas. | * ''\"'', comillas. | ||
| * ''\\'', barra. | * ''\\'', barra. | ||
| + | |||
| ==== Diferencia de incrementos ==== | ==== Diferencia de incrementos ==== | ||
| Línea 36: | Línea 37: | ||
| */ | */ | ||
| </code> | </code> | ||
| + | * **x++**, incrementa x y retorna el valor original de x. | ||
| + | * **++x**, incrementa x y retorna el nuevo valor. | ||
| + | Debido a que el primero necesita una variable temporal es más lento y por lo tanto es mejor utilizar el segundo. | ||
| ==== Nota sobre los fors ==== | ==== Nota sobre los fors ==== | ||
| Línea 325: | Línea 329: | ||
| MyClass c = b; | MyClass c = b; | ||
| </code> | </code> | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| ==== Problemas de organización ==== | ==== Problemas de organización ==== | ||
| + | Cuando trabajamos en C\C++ y mantenemos un código organizado en distintos ficheros (definiciones en .h y código en .cpp independientes por clases) podemos encontrarnos con pequeños errores que pueden traernos grandes dolores de cabeza, aquí los más comunes: | ||
| + | |||
| + | === La declaración no se encuentra === | ||
| + | El error más básico, símplemente es necesario añadir un ''#include'' al archivo .h donde se encuentra la declaración. Aún así pueden aparecer nuevos problemas como definiciones de distintos tipos pero con igual nombre en distintos .h, lo mejor en este caso es revisar el orden de los ''#include''. \\ | ||
| + | Otro error es cuando un .h incluye otro .h, entonces los .cpp que incluyan al primero tienen incluido por defecto el segundo, si por alguna razón se decide borrar la inclusión del segundo .h en el primero el fichero .cpp tendrá grandes posivilidades de no compilar, la clave es incluir explícitamente los .h que necesites para cada fichero en cada uno de los .cpp necesarios. | ||
| + | |||
| + | === Definiciones cruzadas === | ||
| + | Imaginemos el caso de dos clases, una padre que ha de almacenar la clase hijo y una hijo que ha de almacenar la clase padre: | ||
| + | <code cpp> | ||
| + | /* Parent.h */ | ||
| + | #include "child.h" | ||
| + | class Parent { | ||
| + | Child* theChild; | ||
| + | }; | ||
| + | |||
| + | /* Child.h */ | ||
| + | #include "parent.h" | ||
| + | class Child { | ||
| + | Parent* theParent; | ||
| + | }; | ||
| + | </code> | ||
| + | El padre necesita de la declaración del hijo y el hijo de la del padre, pero cuando se está compilando el hijo se hace una inclusión de la cabecera del padre que a la vez incluye la del hijo y el compilador acaba haciendose la picha'un lío. Si eliminas alguno de los include el compilador saltará indicando que el identificador que se necesita no se ha declarado. \\ | ||
| + | Es entonces cuando necesitamos hacer uso de una "declaración posterior" (fordward declaration): | ||
| + | <code cpp> | ||
| + | /* Parent.h */ | ||
| + | class Child; /* Forward declaration of Child; */ | ||
| + | class Parent | ||
| + | { | ||
| + | Child* theChild; | ||
| + | }; | ||
| + | </code> | ||
| + | |||
| + | {{ highlevel:c:gdarticle_cyclic1.png |}} | ||
| + | |||
| + | === Otros errores comunes === | ||
| + | * Su un código A.cpp y otro B.cpp hacen un #include de header.h, cuando se compile el primero no habrá problemas, pero al compilarse el segundo volverá a compilarse header.h y el compilador dará error. Para solucionarlo podemos utilizar las directivas del preprocesador, ya sea el [[highlevel:c#uso_del_ifndef|ifndef]] o el [[highlevel:c#pragma|pragma once]]. | ||
| + | * Puede que tengas una variable global en un fichero .h a la cual accedan dos .cpp, si esto ocurriese se crearían dos copias en memoria de dicha variable, con el mismo nombre produciendo un error del compilador... Únicamente has de declarar dicha variable como [[highlevel:c#extern|extern]] | ||
| + | === Otros consejos === | ||
| + | * Cuando trabajes con la STL no pongas el ''using namespace'' en el archivo .h ya que reduce la efectividad de estos, lo mejor es utilizar el ''using'' en los ficheros .cpp y colocar el nombre completo en los .h. | ||
| + | * Evitar las macros en C++, lo mejor es utilizar las palabras ''const'' o ''inline'' en sus respectivos casos necesarios. Pero sobretodo evita añadir las macros a los .h, en vez de eso, si no puedes esquivarlas, definelas en los mismos .cpp. | ||
| ===== std ===== | ===== std ===== | ||
| Línea 335: | Línea 386: | ||
| * [[highlevel:c:advancing#smart_pointers|auto_ptr]] | * [[highlevel:c:advancing#smart_pointers|auto_ptr]] | ||
| Aún así, quedan elementos por ver: | Aún así, quedan elementos por ver: | ||
| + | |||
| + | |||
| + | |||
| ==== Los mapas ==== | ==== Los mapas ==== | ||
| Los hashmaps y diccionarios de Java tienen su equivalente en C++ en la clase ''std::map<tipo1, tipo2>''. \\ | Los hashmaps y diccionarios de Java tienen su equivalente en C++ en la clase ''std::map<tipo1, tipo2>''. \\ | ||
| + | * Declaración | ||
| + | <code cpp> | ||
| + | std::map<std::string, std::string> configMap; | ||
| + | </code> | ||
| + | * Insertar | ||
| + | <code cpp> | ||
| + | configMap.insert(std::pair<std::string, std::string>(Name, Value)); | ||
| + | </code> | ||
| + | * Modificar | ||
| + | <code cpp> | ||
| + | this->configMap[name] = value; | ||
| + | </code> | ||
| + | * Consultar | ||
| + | <code cpp> | ||
| + | std::string value = this->configMap[name]; | ||
| + | </code> | ||
| + | * Recorrer | ||
| + | <code cpp> | ||
| + | std::map<std::string, std::string>::iterator it; | ||
| + | for(it = this->configMap.begin(); it != this->configMap.end(); ++it) { | ||
| + | std::string strKey = it->first; | ||
| + | std::string strValue = it->second; | ||
| + | } | ||
| + | </code> | ||
| + | * Saber si existe una clave (se llama al método find, si este devuelve ''mapa.end()'' es que no): | ||
| + | <code cpp> | ||
| + | std::map<std::string, std::string>::iterator it = myMap.find("adios"); | ||
| + | if (it == myMap.end()) ... // No encontrado | ||
| + | </code> | ||
| + | |||
| + | ==== Las listas ==== | ||
| + | Con funcionalidad parecida a la de los vectores con la diferencia que las listas están optimizadas para insertar\modificar mientras que los vectores para el acceso. | ||
| + | ==== El buffer de strings ==== | ||
| + | Para montar un string como si escribisiesemos por pantalla podemos disponer del objeto ''ostringstream'': | ||
| + | <code cpp> | ||
| + | std::ostringstream buf ; | ||
| + | buf << "The value of integer a is " << a << "and float f is "<< f << endl ; | ||
| + | std::string str = buf.str() ; | ||
| + | </code> | ||
| ==== Uso de "qsort" ==== | ==== Uso de "qsort" ==== | ||