c++ - programacion - Definición de miembros enteros const enteros en la definición de clase
get y set c++ ejemplos (7)
C ++ permite que los miembros static const sean definidos dentro de una clase
No, 3.1 §2 dice:
Una declaración es una definición a menos que declare una función sin especificar el cuerpo de la función (8.4), contenga el especificador externo (7.1.1) o una especificación de enlace (7.5) y ni un inicializador ni un cuerpo funcional, declara datos estáticos miembro en una definición de clase (9.4), es una declaración de nombre de clase (9.1), es una declaración enum opaco (7.2), o es una declaración typedef (7.1.3), una declaración de uso (7.3. 3), o una directiva de uso (7.3.4).
Mi comprensión es que C ++ permite que los miembros static const se definan dentro de una clase siempre que sea un tipo entero.
¿Por qué, entonces, el siguiente código me da un error de enlazador?
#include <algorithm>
#include <iostream>
class test
{
public:
static const int N = 10;
};
int main()
{
std::cout << test::N << "/n";
std::min(9, test::N);
}
El error que recibo es:
test.cpp:(.text+0x130): undefined reference to `test::N''
collect2: ld returned 1 exit status
Curiosamente, si comulgo la llamada a std :: min, el código compila y enlaza muy bien (aunque test :: N también se menciona en la línea anterior).
¿Alguna idea de lo que está pasando?
Mi compilador es gcc 4.4 en Linux.
A partir de C ++ 11 puedes (y quieres) usar:
static constexpr int N = 10;
eso no requiere que definas la constante en un archivo .cpp.
Aquí hay otra forma de evitar el problema:
std::min(9, int(test::N));
(Creo que la respuesta de Crazy Eddie describe correctamente por qué existe el problema).
El ejemplo de Bjarne Stroustrup en su C ++ FAQ sugiere que usted es correcto, y solo necesita una definición si toma la dirección.
class AE {
// ...
public:
static const int c6 = 7;
static const int c7 = 31;
};
const int AE::c7; // definition
int f()
{
const int* p1 = &AE::c6; // error: c6 not an lvalue
const int* p2 = &AE::c7; // ok
// ...
}
Él dice "Puedes tomar la dirección de un miembro estático si (y solo si) tiene una definición fuera de clase" . Lo que sugiere que funcionaría de otra manera. Tal vez su función mínima invoca direcciones de alguna manera detrás de la escena.
No solo int. Pero no puede definir el valor en la declaración de clase. Si usted tiene:
class classname
{
public:
static int const N;
}
en el archivo .h, entonces debes tener:
int const classname::N = 10;
en el archivo .cpp.
Otra forma de hacerlo, para tipos enteros de todos modos, es definir constantes como enumeraciones en la clase:
class test
{
public:
enum { N = 10 };
};
Mi comprensión es que C ++ permite que los miembros static const se definan dentro de una clase siempre que sea un tipo entero.
Estás en cierto modo correcto. Se le permite inicializar integrales estást const en la declaración de clase, pero eso no es una definición.
Curiosamente, si comulgo la llamada a std :: min, el código compila y enlaza muy bien (aunque test :: N también se menciona en la línea anterior).
¿Alguna idea de lo que está pasando?
std :: min toma sus parámetros por referencia constante. Si les tomó por valor, no tendrían este problema, pero dado que necesitan una referencia, también necesitan una definición.
Aquí está el capítulo / verso:
9.4.2 / 4 - Si un miembro de datos static
es de tipo const
integral o const
enumeration, su declaración en la definición de clase puede especificar un constante-inicializador que será una expresión de constante integral (5.19). En ese caso, el miembro puede aparecer en expresiones constantes integrales. El miembro aún se definirá en un ámbito de espacio de nombres si se usa en el programa y la definición del alcance del espacio de nombres no contendrá un inicializador .
Vea la respuesta de Chu para una posible solución alternativa.