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/28 18:32] alfred |
highlevel:c:xtra [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| - | ====== Xtra ====== | + | ====== C\C++ Xtra ====== |
| ===== Lenguaje ===== | ===== Lenguaje ===== | ||
| Línea 329: | Línea 329: | ||
| MyClass c = b; | MyClass c = b; | ||
| </code> | </code> | ||
| + | |||
| Línea 369: | Línea 370: | ||
| {{ highlevel:c:gdarticle_cyclic1.png |}} | {{ highlevel:c:gdarticle_cyclic1.png |}} | ||
| - | === Título 4 === | ||
| - | |||
| - | === Título 4 === | ||
| + | === 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 === | === 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. | * 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. | * 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. | ||
| - | |||
| - | ==== Bibliotecas (libraries) ==== | ||
| - | Una biblioteca es una colección de código que permite hacer dicho código independiente del programa en el que se añaden, esto hace que el código pueda ser estructurado y reutilzado de forma modular. Existen dos tipos de bibliotecas: | ||
| - | * Estáticas, se añaden al programa, en el mismo archivo, en tiempo de compilación. | ||
| - | * Dinámicas, se cargan y se enlazan al programa en el momento en el que este lo necesita, durante el tiempo de ejecución. En sistemas Windows son llamadas DLL y pueden tener como extensión .dll, .ocx (si incluyen un control ActiveX) o .drv (si pertenecen a un driver). | ||
| - | [[code:tools#tips_creando_bibliotecas|Tips para crear bibliotecas desde Visual Studio]] | ||
| - | |||
| - | === Crear una biblioteca (Windows) === | ||
| - | Cuando se va a utilizar una librería dinámica en un programa es necesario que se proporcionen dos archivos, un .h (mediante un #include) y un .lib (esta debe ser vinculada desde el compilador), en el primero estará el código de dicha biblioteca y en el segundo un mapeo al archivo .dll. \\ | ||
| - | Al crear la librería hay que tener en cuenta las siguientes cosas: | ||
| - | * En el archivo .h del código correspondiente a la biblioteca añadiremos ''<nowiki>extern "C" _declspec(dllexport)</nowiki>'' antes de cada función que queramos que sea utilizable en la biblioteca. | ||
| - | * El archivo .h que se añadirá al código del programa debe de contener ''<nowiki>extern "C" _declspec(dllimport)</nowiki>'' delante de cada declaración de función. | ||
| - | <code> | ||
| - | /*************** Proyecto Librería **********************/ | ||
| - | // lib.h | ||
| - | extern "C" _declspec(dllexport) int suma (int); | ||
| - | |||
| - | // lib.cpp | ||
| - | #include "lib.h" | ||
| - | int suma (int a) { | ||
| - | return a + 4; | ||
| - | } | ||
| - | |||
| - | /*************** Proyecto Ejecutable **********************/ | ||
| - | // bin.h | ||
| - | extern "C" _declspec(dllimport) int suma (int); | ||
| - | |||
| - | // bin.cpp | ||
| - | #include <iostream> | ||
| - | #include <stdlib.h> | ||
| - | #include "lib.h" | ||
| - | |||
| - | void main () { | ||
| - | std::cout << suma(33) << std::endl; | ||
| - | system("pause"); | ||
| - | } | ||
| - | </code> | ||
| - | * La parte del **''<nowiki>extern "C"</nowiki>''** no es necesaria en algunos compiladores. | ||
| - | * Respecto a importar\exportar clases la sintaxis es: ''<nowiki>class _declspec(dllimport) nombreClase</nowiki>''. En la cabecera del ejecutable no sería necesario añadir los privates. | ||
| - | <code cpp> | ||
| - | /*************** Proyecto Librería **********************/ | ||
| - | // lib.h | ||
| - | class _declspec(dllimport) A { | ||
| - | private: | ||
| - | int suma (int i); | ||
| - | public: | ||
| - | int haz (int i); | ||
| - | }; | ||
| - | |||
| - | /*************** Proyecto Ejecutable **********************/ | ||
| - | // bin.h | ||
| - | // lib.h | ||
| - | class _declspec(dllimport) A { | ||
| - | public: | ||
| - | int haz (int i); | ||
| - | }; | ||
| - | </code> | ||
| - | |||
| - | === Palabra clave extern === | ||
| - | La palabra clave ''extern'' indica al compilador que el dato que se está definiendo existe en algún lugar del código (más abajo, en un fichero externo...), pero que es posible que todavía no se haya compilado esa parte. | ||
| - | <code cpp> | ||
| - | extern int i; | ||
| - | extern void func(); | ||
| - | int main() { | ||
| - | i = 0; | ||
| - | func(); | ||
| - | } | ||
| - | int i; | ||
| - | void func() { | ||
| - | i++; | ||
| - | cout << i; | ||
| - | } | ||
| - | </code> | ||
| ===== std ===== | ===== std ===== | ||
| Línea 458: | 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 ==== | ==== Las listas ==== | ||