una tipos son programacion las formas define declarar declara cuales crear constantes constante como c++ header constants

tipos - Definir variables constantes en el encabezado de C++.



variables y constantes en c++ (6)

Un programa en el que estoy trabajando tiene muchas constantes que se aplican en todas las clases. Quiero hacer un archivo de encabezado "Constantes.h" y poder declarar todas las constantes relevantes. Luego, en mis otras clases, solo puedo incluir #include "Constants.h .

Conseguí que funcionara bien usando la #ifndef ... #define ... Sin embargo, preferiría usar la forma constante de constantes. No estoy muy seguro de cómo hacerlo.


En lugar de hacer un montón de variables globales, puede considerar crear una clase que tenga un montón de constantes estáticas públicas. Todavía es global, pero de esta manera está envuelto en una clase para que sepas de dónde viene la constante y que se supone que es una constante.

Constantes.h

#ifndef CONSTANTS_H #define CONSTANTS_H class GlobalConstants { public: static const int myConstant; static const int myOtherConstant; }; #endif

Constantes.cpp

#include "Constants.h" const int GlobalConstants::myConstant = 1; const int GlobalConstants::myOtherConstant = 3;

Entonces puedes usar esto así:

#include "Constants.h" void foo() { int foo = GlobalConstants::myConstant; }


Me gusta el espacio de nombres mejor para este tipo de propósito.

Opción 1 :

#ifndef MYLIB_CONSTANTS_H #define MYLIB_CONSTANTS_H // File Name : LibConstants.hpp Purpose : Global Constants for Lib Utils namespace LibConstants { const int CurlTimeOut = 0xFF; // Just some example ... } #endif // source.cpp #include <LibConstants.hpp> int value = LibConstants::CurlTimeOut;

Opcion 2 :

#ifndef MYLIB_CONSTANTS_H #define MYLIB_CONSTANTS_H // File Name : LibConstants.hpp Purpose : Global Constants for Lib Utils namespace CurlConstants { const int CurlTimeOut = 0xFF; // Just some example ... } namespace MySQLConstants { const int DBPoolSize = 0xFF; // Just some example ... } #endif // source.cpp #include <LibConstants.hpp> int value = CurlConstants::CurlTimeOut; int val2 = MySQLConstants::DBPoolSize;

Y nunca usaría una clase para mantener este tipo de variables constantes de HardCoded.


No puede usar, por ejemplo, const int en un archivo de encabezado, si está incluido en varios archivos de origen. Esto se debe a que las variables se definirán en todos los archivos de origen (unidades de traducción técnicamente hablando). Debe tener un archivo fuente especial, Constants.cpp que realmente define las variables, y luego tener las variables declaradas como extern en el archivo de encabezado.

Algo así como este archivo de cabecera:

// Protect against multiple inclusions in the same source file #ifndef CONSTANTS_H #define CONSTANTS_H extern const int CONSTANT_1; #endif

Y esto en un archivo fuente:

const int CONSTANT_1 = 123;


Parece que la respuesta de bames53 se puede extender a la definición de valores constantes enteros y no enteros en el espacio de nombres y en las declaraciones de clase, incluso si se incluyen en varios archivos de origen. No es necesario colocar las declaraciones en un archivo de cabecera, sino las definiciones en un archivo de origen. El siguiente ejemplo funciona para Microsoft Visual Studio 2015, para z / OS V2.2 XL C / C ++ en OS / 390 y para g ++ (GCC) 8.1.1 20180502 en GNU / Linux 4.16.14 (Fedora 28). Tenga en cuenta que las constantes se declaran / definen en un solo archivo de encabezado que se incluye en varios archivos de origen.

En foo.cc:

#include <cstdio> // for puts #include "messages.hh" #include "bar.hh" #include "zoo.hh" int main(int argc, const char* argv[]) { puts("Hello!"); bar(); zoo(); puts(Message::third); return 0; }

En mensajes.hh:

#ifndef MESSAGES_HH #define MESSAGES_HH namespace Message { char const * const first = "Yes, this is the first message!"; char const * const second = "This is the second message."; char const * const third = "Message #3."; }; #endif

En bar.cc:

#include "messages.hh" #include <cstdio> void bar(void) { puts("Wow!"); printf("bar: %s/n", Message::first); }

En zoo.cc:

#include <cstdio> #include "messages.hh" void zoo(void) { printf("zoo: %s/n", Message::second); }

En bar.hh:

#ifndef BAR_HH #define BAR_HH #include "messages.hh" void bar(void); #endif

En zoo.hh:

#ifndef ZOO_HH #define ZOO_HH #include "messages.hh" void zoo(void); #endif

Esto produce el siguiente resultado:

Hello! Wow! bar: Yes, this is the first message! zoo: This is the second message. Message #3.

El tipo de datos char const * const significa un puntero constante a una matriz de caracteres constantes. La primera const es necesaria porque (según g ++) "ISO C ++ prohíbe convertir una constante de cadena a ''char *''". La segunda const es necesaria para evitar errores de enlace debido a las múltiples definiciones de las constantes (entonces no lo suficientemente constantes). Es posible que su compilador no se queje si omite una o ambas const , pero entonces el código fuente es menos portátil.


Simplemente podría definir una serie de const ints en un archivo de encabezado:

// Constants.h #if !defined(MYLIB_CONSTANTS_H) #define MYLIB_CONSTANTS_H 1 const int a = 100; const int b = 0x7f; #endif

Esto funciona porque en C ++ un nombre en el ámbito del espacio de nombres (incluido el espacio de nombres global) que se declara explícitamente const y no se declara externamente explícitamente tiene vinculación interna, por lo que estas variables no causarán símbolos duplicados cuando vincule unidades de traducción. Alternativamente, podría declarar explícitamente las constantes como estáticas.

static const int a = 100; static const int b = 0x7f;

Esto es más compatible con C y más legible para las personas que pueden no estar familiarizadas con las reglas de enlace de C ++.

Si todas las constantes son ints, entonces otro método que podría usar es declarar los identificadores como enumeraciones.

enum mylib_constants { a = 100; b = 0x7f; };

Todos estos métodos usan solo un encabezado y permiten que los nombres declarados se usen como constantes de tiempo de compilación. El uso de la extern const int y un archivo de implementación separado evita que los nombres se utilicen como constantes de tiempo de compilación.

Tenga en cuenta que la regla que hace que ciertas constantes implícitamente se vinculen internamente se aplica a los punteros, exactamente como constantes de otros tipos. Sin embargo, lo complicado es que marcar un puntero como const requiere una sintaxis un poco diferente que la mayoría de la gente usa para hacer constantes de variables de otros tipos. Necesitas hacer:

int * const ptr;

para hacer un puntero constante, para que la regla se aplique a ella.

También tenga en cuenta que esta es una razón por la que prefiero poner const después del tipo: int const lugar de const int . También puse el * junto a la variable: es decir, int *ptr; en lugar de int* ptr; .

Me gusta hacer este tipo de cosas porque reflejan el caso general de cómo funciona realmente C ++. Las alternativas ( const int , int* p ) son especiales para facilitar la lectura de algunas cosas simples. El problema es que cuando se sale de esos casos simples, las alternativas de caja especial se vuelven activamente engañosas.

Entonces, aunque los ejemplos anteriores muestran el uso común de const , en realidad recomendaría que las personas los escriban así:

int const a = 100; int const b = 0x7f;

y

static int const a = 100; static int const b = 0x7f;


El proyecto estándar de C ++ 17 en const implica static

Esta es la cita de lo que se mencionó en: https://.com/a/12043198/895245

C ++ 17 n4659 borrador estándar 6.5 "Programa y vinculación":

3 Un nombre que tenga un ámbito de espacio de nombres (6.3.6) tiene un enlace interno si es el nombre de

  • (3.1) - una variable, función o plantilla de función que se declara explícitamente como estática; o,
  • (3.2) - una variable no en línea de tipo cualificado por const no volátil que no se declara explícitamente como externamente ni se declaró anteriormente que tiene un enlace externo; o
  • (3.3) - un miembro de datos de una unión anónima.

constexpr

Es probable que desee utilizar constexpr para este caso de uso simple, ya que también se podría usar en contextos como plantillas. Vea también: Diferencia entre `constexpr` y` const` .