OVH Cloud OVH Cloud

Initialisation de tableaux membres

18 réponses
Avatar
Vincent Jacques
Bonjour à tous,

comment initialise-t-on un tableau membre d'une classe ?

class A
{
public:
A(int);
// Pas de constructeur par défaut
};

A::A(int)
{
};

class B
{
public:
B();
private:
A tableau[5];
};

B::B() :
tableau( ??????? )
{
// Je ne peux pas me contenter d'affectations dans une boucle ici,
puisque A n'a pas de constructeur par défaut.
}

Merci d'avance pour votre aide,
--
Vincent Jacques

"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème."
Devise Shadok

10 réponses

1 2
Avatar
Alexandre
bonjour,

comment initialise-t-on un tableau membre d'une classe ?

class A
{
public:
A(int);
// Pas de constructeur par défaut
};

A::A(int)
{
};

class B
{
public:
B();
private:
A tableau[5];


ceci n'est pas vraiment un tableau, mais un pointeur. Je sais, je pinaille,
mais pour expliquer que l'initialisation ne sera pas possible...

};

B::B() :
tableau( ??????? )
{
// Je ne peux pas me contenter d'affectations dans une boucle ici,
puisque A n'a pas de constructeur par défaut.


mais à quelle valeur veux-tu initialiser ? La même valeur pour tous ? Une
constante ?
Moi j'utiliserai std::vector, comme ceci :

class B
{
private:
std::vector<A> tableau;
public:
B();
};

B::B():tableau(5,A(0))
{ //....
}

Si tu veux A(0) comme valeur par défaut dans le vector.

Avatar
Fabien LE LEZ
On Fri, 4 Nov 2005 19:29:59 +0100, "Alexandre"
:

A tableau[5];


ceci n'est pas vraiment un tableau, mais un pointeur.


Pas vraiment un pointeur non plus, puisque
sizeof tableau == 5 * sizeof(A).

mais à quelle valeur veux-tu initialiser ?


J'imagine qu'il voulait un truc du genre :

int tableau[]= { 12, 36, 87, 54, 1 };


Avatar
Jean-Marc Bourguet
"Alexandre" writes:

A tableau[5];


ceci n'est pas vraiment un tableau, mais un pointeur. Je sais, je pinaille,
mais pour expliquer que l'initialisation ne sera pas possible...


C'est un tableau, certainement pas un pointeur.

A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Vincent Jacques
A tableau[5];
ceci n'est pas vraiment un tableau, mais un pointeur. Je sais, je pinaille,

mais pour expliquer que l'initialisation ne sera pas possible...


Ben... si, c'est un tableau, c'est pas pareil qu'un pointeur, même si ça
se ressemble un peu de loin.

B::B() :
tableau( ??????? )
{
// Je ne peux pas me contenter d'affectations dans une boucle ici,
puisque A n'a pas de constructeur par défaut.



mais à quelle valeur veux-tu initialiser ? La même valeur pour tous ? Une
constante ?


Dans mon cas particulier, les objets à placer dans le tableau sont
construit en fonction d'un paramètre du constructeur de B. Un truc du genre:

B::B(int i):
tableau( {A(1,i),A(5,i),A(3,i),A(5,i),A(0,i)} )
{};

Mais ça ça compile pas :-(

--
Vincent Jacques

"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème."
Devise Shadok


Avatar
Fabien LE LEZ
On Sat, 05 Nov 2005 00:18:06 +0100, Vincent Jacques
:

Mais ça ça compile pas :-(


Ben non.
Si un objet de classe A est copiable, le plus simple est d'utiliser
std::vector<> :

class B
{
public:
B(int i);
private:
std::vector<A> tableau;
};

B::B (int i)
{
tableau.push_back (A(1,i));
tableau.push_back (A(5,i));
tableau.push_back (A(3,i));
tableau.push_back (A(5,i));
tableau.push_back (A(0,i));
}

Ou bien :

B::B (int i)
{
static int const initialiseurs[]= { 1,5,3,5,0 };
static int const nb_initialiseurs=
sizeof initialiseurs / sizeof *initialiseurs;
for (int j=0; j<nb_initialiseurs; ++j)
{
tableau.push_back (A(j,i));
}
}

[Note : il y a des méthodes plus sophistiquées pour faire ça, avec des
jolis back_inserter, mais je préfère les méthodes simples.]

Note bis : j'imagine que dans le vrai code, les identifiants sont plus
explicites que "A", "B", "tableau" et "i".

Avatar
James Kanze
Alexandre wrote:

comment initialise-t-on un tableau membre d'une classe ?



class A
{
public:
A(int);
// Pas de constructeur par défaut
};



A::A(int)
{
};



class B
{
public:
B();
private:
A tableau[5];



ceci n'est pas vraiment un tableau, mais un pointeur.


Dans quel langage ? En C++, c'est un tableau. Même si la plupart
du temps, on écrirait plutôt :
std::vector< A > tableau ;
il reste des cas où les « bons » vieux tableaux de C sont à
préférer.

Je sais, je pinaille, mais pour expliquer que l'initialisation
ne sera pas possible...


Son initialisation n'est pas possible parce que la norme ne
prévoit pas de syntaxe pour le faire. C'est la seule raison.

};



B::B() :
tableau( ??????? )
{
// Je ne peux pas me contenter d'affectations dans une boucle ici,
puisque A n'a pas de constructeur par défaut.



mais à quelle valeur veux-tu initialiser ? La même valeur pour
tous ? Une constante ?


On pourrait très bien imaginer un « compound literal », répris
de C, e.g. :

: tableau( (A[5]){ v1, v2, v3, v4, v5 } )

Sinon, on pourrait simplement considérer que les types tableaux
se comportent ici comme s'ils étaient implicitement emballés
dans un struct sans nom, ce qui permettra

: tableau( init )

où init serait une variable à durée de vie statique, par
exemple :

A init[] = { 1, 2, 3, 4, 5 } ;

On pourrait même imaginer des solutions plus complexes, comme
par exemple de dire qu'un tableau a un constructeur implicit :

template< typename InputIter >
TableauType::TableauType( InputIter begin, InputIter end )
{
size_t i = 0 ;
while ( i < N && begin != end ) {
(*this)[ i ++ ] = *begin ++ ;
}
while ( i < N ) {
(*this)[ i ++ ] = 0 ;
}
}

(Note que tout ceci ne sont que des idées vagues des choses
qu'on pourraient considérer. Je ne saurais dire à présent s'il
sont réelement faisable ou intéressant -- dans tous les cas, il
faudrait restreindre leur champ d'application pour éviter des
problèmes d'incompatibilité C.)

Moi j'utiliserai std::vector, comme ceci :


class B
{
private:
std::vector<A> tableau;
public:
B();
};


B::B():tableau(5,A(0))
{ //....
}


Si tu veux A(0) comme valeur par défaut dans le vector.


Plus couramment, on utilise le constructeur à deux itérateurs,
pour l'initialiser à partir d'un tableau de type C :

static A init[] = { ... } ;

B::B()
: tableau( begin( init ), end( init ) )
{
// ...
}

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
Vincent Jacques
[trop de choses pour que je cite tout]

Merci beaucoup pour ces pistes.
--
Vincent Jacques

"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème."
Devise Shadok
Avatar
James Kanze
Vincent Jacques wrote:

A tableau[5];




ceci n'est pas vraiment un tableau, mais un pointeur. Je
sais, je pinaille, mais pour expliquer que l'initialisation
ne sera pas possible...



Ben... si, c'est un tableau, c'est pas pareil qu'un pointeur,
même si ça se ressemble un peu de loin.


B::B() :
tableau( ??????? )
{
// Je ne peux pas me contenter d'affectations dans une boucle ici,
puisque A n'a pas de constructeur par défaut.




mais à quelle valeur veux-tu initialiser ? La même valeur
pour tous ? Une constante ?



Dans mon cas particulier, les objets à placer dans le tableau
sont construit en fonction d'un paramètre du constructeur de
B. Un truc du genre:


B::B(int i):
tableau( {A(1,i),A(5,i),A(3,i),A(5,i),A(0,i)} )
{};


Mais ça ça compile pas :-(


C'est plus compliqué. Si tableau est un std::vector< A >, en
revanche, il suffit de définir un itérateur conventable pour
pouvoir écrire quelque chose du genre :

int p1[] = { 1, 5, 3, 5, 0 } ;

B::B( int i )
: tableau( MyIter( begin( p1 ) ), MyIter( end( p1 ) ) )
{
}

(L'utilisation de boost::iterator_facade ou
boost::iterator_adaptor me semble indiquée.)

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34



Avatar
Alexandre
ceci n'est pas vraiment un tableau, mais un pointeur. Je sais, je
pinaille,
mais pour expliquer que l'initialisation ne sera pas possible...


C'est un tableau, certainement pas un pointeur.


pas vraiment :
int tab1[5], tab2[5];

tab1=tab2 ne produit pas une recopie du tableau. Ce n'est pas une sémantique
de valeur. Pas vraiment un tableau, quoi, mais un pointeur "caché"



A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF:
http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Alexandre
ceci n'est pas vraiment un tableau, mais un pointeur.


Dans quel langage ? En C++, c'est un tableau.


je ne trouve pas, au sens littéral du terme, puisque la variable tableau
n'est ni copiable ni assignable, elle possède plutôt une sémantique
d'adresse. Donc pour moi, au sens strict, ce n'est pas un tableau. ça peut
s'utiliser comme.


il reste des cas où les « bons » vieux tableaux de C sont à
préférer.


tout à fait, d'ailleurs ça m'arrive très souvent, mais je trouve que le
terme "tableau" est un peu usurpé ici. De même, peut-on vraiment dire qu'un
(char *) est une chaîne de caractères ?


1 2