miembros estaticos estaticas c++ initialization c++03 array-initialize

estaticas - miembros estaticos c++



Inicializar una matriz de const en un inicializador de clase en C++ (10)

¿Qué tal si se emula una matriz de const a través de una función de acceso? No es estático (como solicitó), y no requiere stl ni ninguna otra biblioteca:

class a { int privateB[2]; public: a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; } int b(const int idx) { return privateB[idx]; } }

Como a :: privateB es privado, es efectivamente constante fuera de a ::, y puede acceder a él de forma similar a una matriz, por ejemplo

a aobj(2,3); // initialize "constant array" b[] n = aobj.b(1); // read b[1] (write impossible from here)

Si está dispuesto a usar un par de clases, también puede proteger privateB de las funciones de miembro. Esto se puede hacer heredando a; pero creo que prefiero la publicación comp.lang.c ++ de John Harrison usando una clase const.

Tengo la siguiente clase en C ++:

class a { const int b[2]; // other stuff follows // and here''s the constructor a(void); }

La pregunta es, ¿cómo inicializo b en la lista de inicialización, dado que no puedo inicializarlo dentro del cuerpo de la función del constructor, porque b es const ?

Esto no funciona:

a::a(void) : b([2,3]) { // other initialization stuff }

Editar: El caso en el punto es cuando puedo tener diferentes valores para b para diferentes instancias, pero se sabe que los valores son constantes durante la vida de la instancia.


Al igual que los otros dijeron, ISO C ++ no es compatible. Pero puedes solucionarlo. Solo use std :: vector en su lugar.

int* a = new int[N]; // fill a class C { const std::vector<int> v; public: C():v(a, a+N) {} };


Con C ++ 11, la respuesta a esta pregunta ha cambiado y de hecho puedes:

struct a { const int b[2]; // other bits follow // and here''s the constructor a(); }; a::a() : b{2,3} { // other constructor work } int main() { a a; }


Donde tengo una matriz constante, siempre se ha hecho como estático. Si puede aceptar eso, este código debería compilarse y ejecutarse.

#include <stdio.h> #include <stdlib.h> class a { static const int b[2]; public: a(void) { for(int i = 0; i < 2; i++) { printf("b[%d] = [%d]/n", i, b[i]); } } }; const int a::b[2] = { 4, 2 }; int main(int argc, char **argv) { a foo; return 0; }


El estándar ISO C ++ no te permite hacer esto. Si lo hiciera, la sintaxis probablemente sería:

a::a(void) : b({2,3}) { // other initialization stuff }

O algo por el estilo. De su pregunta, en realidad parece que lo que desea es un miembro de clase constante (también conocido como estático) que es la matriz. C ++ te deja hacer esto. Al igual que:

#include <iostream> class A { public: A(); static const int a[2]; }; const int A::a[2] = {0, 1}; A::A() { } int main (int argc, char * const argv[]) { std::cout << "A::a => " << A::a[0] << ", " << A::a[1] << "/n"; return 0; }

El resultado es:

A::a => 0, 1

Ahora, por supuesto, dado que este es un miembro de clase estático, es el mismo para cada instancia de clase A. Si eso no es lo que quieres, es decir, quieres que cada instancia de A tenga diferentes valores de elementos en la matriz a, entonces estás haciendo el error de tratar de hacer la matriz const para comenzar. Deberías estar haciendo esto:

#include <iostream> class A { public: A(); int a[2]; }; A::A() { a[0] = 9; // or some calculation a[1] = 10; // or some calculation } int main (int argc, char * const argv[]) { A v; std::cout << "v.a => " << v.a[0] << ", " << v.a[1] << "/n"; return 0; }


No es posible en el estándar actual. Creo que podrás hacer esto en C ++ 0x utilizando las listas de inicializadores (consulta Una breve reseña de C ++ 0x , de Bjarne Stroustrup, para obtener más información sobre las listas de inicializadores y otras características agradables de C ++ 0x).



Una solución sin usar el montón con std::vector es usar boost::array , aunque no puede inicializar los miembros de la matriz directamente en el constructor.

#include <boost/array.hpp> const boost::array<int, 2> aa={ { 2, 3} }; class A { const boost::array<int, 2> b; A():b(aa){}; };


curiosamente, en C # tiene la palabra clave const que se traduce en const estático de C ++, en oposición a readonly que solo se puede establecer en constructores e inicializaciones, incluso por no constantes, por ejemplo:

readonly DateTime a = DateTime.Now;

Estoy de acuerdo, si tienes un conjunto predefinido de const, también puedes hacerlo estático. En ese momento puedes usar esta interesante sintaxis:

//in header file class a{ static const int SIZE; static const char array[][10]; }; //in cpp file: const int a::SIZE = 5; const char array[SIZE][10] = {"hello", "cruel","world","goodbye", "!"};

sin embargo, no encontré una forma de el constante ''10''. Sin embargo, la razón es clara, necesita saber cómo realizar el acceso a la matriz. Una posible alternativa es usar #define, pero no me gusta ese método y I #undef al final del encabezado, con un comentario para editar también en CPP, así en caso de un cambio.


std::vector usa el montón. Caray, qué desperdicio sería por el simple hecho de una comprobación de cordura. El objetivo de std::vector es el crecimiento dinámico en tiempo de ejecución, no cualquier antigua comprobación de sintaxis que deba hacerse en tiempo de compilación. Si no vas a crecer, crea una clase para envolver una matriz normal.

#include <stdio.h> template <class Type, size_t MaxLength> class ConstFixedSizeArrayFiller { private: size_t length; public: ConstFixedSizeArrayFiller() : length(0) { } virtual ~ConstFixedSizeArrayFiller() { } virtual void Fill(Type *array) = 0; protected: void add_element(Type *array, const Type & element) { if(length >= MaxLength) { // todo: throw more appropriate out-of-bounds exception throw 0; } array[length] = element; length++; } }; template <class Type, size_t Length> class ConstFixedSizeArray { private: Type array[Length]; public: explicit ConstFixedSizeArray( ConstFixedSizeArrayFiller<Type, Length> & filler ) { filler.Fill(array); } const Type *Array() const { return array; } size_t ArrayLength() const { return Length; } }; class a { private: class b_filler : public ConstFixedSizeArrayFiller<int, 2> { public: virtual ~b_filler() { } virtual void Fill(int *array) { add_element(array, 87); add_element(array, 96); } }; const ConstFixedSizeArray<int, 2> b; public: a(void) : b(b_filler()) { } void print_items() { size_t i; for(i = 0; i < b.ArrayLength(); i++) { printf("%d/n", b.Array()[i]); } } }; int main() { a x; x.print_items(); return 0; }

ConstFixedSizeArrayFiller y ConstFixedSizeArray son reutilizables.

La primera permite la verificación de límites de tiempo de ejecución al inicializar la matriz (lo mismo que un vector), que luego puede convertirse en const después de esta inicialización.

El segundo permite que la matriz se asigne dentro de otro objeto, que podría estar en el montón o simplemente en la pila, si es allí donde está el objeto. No hay pérdida de tiempo asignando desde el montón. También realiza la comprobación de const en tiempo de compilación en la matriz.

b_filler es una pequeña clase privada para proporcionar los valores de inicialización. El tamaño de la matriz se verifica en tiempo de compilación con los argumentos de la plantilla, por lo que no hay posibilidad de salir de los límites.

Estoy seguro de que hay formas más exóticas de modificar esto. Esta es una puñalada inicial. Creo que puedes compensar las deficiencias del compilador con las clases.