OVH Cloud OVH Cloud

Appel au Constructeur de base

5 réponses
Avatar
dug8C
bonjour,

Je débute en c++ et j'ai un souci avec les construteurs de classes
dérivés.

Je résume mon code
class A : public B
{
B();
B(int x, int y);
~B(){};
}
B::B(){};
B::B(int x, int y)
: A(x,y)
{
// --
}
int main()
{
B b0(1,2);
B* pb1 = new B(1,2);

}

Les constructeurs A() et A(int x, int y) sont déclarés dans la classe
de base.

J'ai constaté que b0 s'initialise avec le constructeur par défaut de A
et affecte x et y à 0
tandis que *pb1 est bien initialisé avec x=1 et y=2.

Est un erreur de ma part ou bien il est nécessaire d'utiliser new pour
initialiser les contructeurs des classes dérivées ?

Merci de vos réponses. :)

5 réponses

Avatar
Andre Heinen
On 26 Feb 2004 01:38:10 -0800, (Dug) wrote:

<snip>

Je résume mon code
class A : public B


Si A est ta classe de base, il faut écrire
class B: public A
Comme d'autre part les membres sont tous privés, et qu'il manque,
outre la classe A, un point-virgule, je suppose que tu ne nous a
pas donné ton code réel. Dans ces conditions, il nous est
difficile de trouver la faute.

D'autre part, si tu nous donne ton code réel, ça risque d'être
long à lire...
;-)

Ecris un programme minimum mais qui compile. Si l'erreur y est
toujours, poste-le.

<snip>

Est un erreur de ma part ou bien il est nécessaire d'utiliser new pour
initialiser les contructeurs des classes dérivées ?


new n'est pas nécessaire.

--
Andre Heinen
My address is "a dot heinen at europeanlink dot com"

Avatar
Gourgouilloult
bonjour,

Je débute en c++ et j'ai un souci avec les construteurs de classes
dérivés.

Je résume mon code
class A : public B
{
B();


Ca, c'est infaisable. A voir la suite, je parierais sur une légère faute
de frappe, avec "class B : public A { ... ", plutôt

B(int x, int y);
~B(){};
}


(Pas oublier le ';' après une classe, même quand on recopie ;)

B::B(){};
B::B(int x, int y)
: A(x,y)
{
// --
}
int main()
{
B b0(1,2);
B* pb1 = new B(1,2);

}

Les constructeurs A() et A(int x, int y) sont déclarés dans la classe
de base.


Ce serait donc très utile de nous donner la définition de la classe de
base (et de ses constructeurs, au moins).

J'ai constaté que b0 s'initialise avec le constructeur par défaut de A
et affecte x et y à 0
tandis que *pb1 est bien initialisé avec x=1 et y=2.


C'est à dire, concrètement, ça donne quoi ? Plus précisément, comment tu
vérifies ça et quel est le résultat précis de ta méthode de vérif. Ca
plus le code de la classe et l'erreur éventuelle sera beaucoup plus
facile à trouver.

Est un erreur de ma part ou bien il est nécessaire d'utiliser new pour
initialiser les contructeurs des classes dérivées ?


Ah, oui, il nous manque une idée précise de ce que tu veux faire. Ca
sera sans doute évident quand on saura plus sur ton code, c'est sans
doute déjà devinable... mais en générale, je préfère éviter de laisser
traîner des «évident» dans les coins ;)

Merci de vos réponses. :)


Ah ben oui, mais ça vient doucement, hein.

Gourgou

Avatar
dug8C
Merci pour ces réponses,

Je poste donc le code qui est un peu différent du résumé ci-dessus:

le code est organisé en 7 fichiers
main.cpp
CPoint2d.cpp et CPoint2d.h, CBox2d.h et CBox2d.cpp, CBrick2d.h et
CBrick2d.cpp

mon but est d'arriver à progammer un casse-brique, pour la partie
graphique ça viendra plus tard :)

Pour l'instant la sortie sur écran donne:
--------------------------------------------------------------------------
BoxCtor g,b,d,h def
box: BoxID:1,p1:PointID:1,x:1.1,y:1.2,p2:PointID:2,x:1.1,y:1.2
BoxCtor g,b,d,h def
BoxCtor g,b,d,h def

bricks:
-------
...Cbox recopie ..*** - br0 b3:
BrickID:3
r:0.7,g:0.8,b:0.1,vie:3...Cbox recopie ..brickbox:
BoxID:5,p1:PointID:15,x:1.1,y:1.2,p2:PointID:16,x:1.1,y:1.2XX--DsTor
CBox:5 --XX


BoxCtor g,b,d,h def
...Cbox recopie .....Cbox recopie ..XX--DsTor CBox:8 --XXXX--DsTor
CBox:7 --XXXX
--DsTor CBox:6 --XX*** - br3 = CBrick2d(0.1f ,0.2f ,0.3f ,5)
BrickID:1
r:0.1,g:0.2,b:0.3,vie:5...Cbox recopie ..brickbox:
BoxID:9,p1:PointID:25,x:0,y:0,p2:PointID:26,x:1,y:0.5XX--DsTor CBox:9
--XX

BoxCtor g,b,d,h def
...Cbox recopie .....Cbox recopie ..XX--DsTor CBox:12 --XXXX--DsTor
CBox:11 --XX
XX--DsTor CBox:10 --XX*** - br4 = CBrick2d(1.5f, 2.6f, 0.1f ,0.2f
,0.3f)
BrickID:2
r:0.1,g:0.2,b:0.3,vie:3...Cbox recopie ..brickbox:
BoxID:13,p1:PointID:35,x:0,y:0,p2:PointID:36,x:1,y:0.5XX--DsTor
CBox:13 --XX

...Cbox recopie .....Cbox recopie ..XX--DsTor CBox:15 --XXXX--DsTor
CBox:14 --XX
*** - br4 = br0 :
BrickID:2
r:0.7,g:0.8,b:0.1,vie:3...Cbox recopie ..brickbox:
BoxID:16,p1:PointID:41,x:0,y:0,p2:PointID:42,x:1,y:0.5XX--DsTor
CBox:16 --XX

Appuyez sur une touche pour continuer...
---------------------------------------------------------------------

Le problème est que les br3 et br4 s'initialisent avec le constructeur
par défaut alors que j'appelle explicitement un autre constructeur de
la classe de base.

Je pense que le problème vient du constructeur de recopie de CBrick2d
mais je n'en suis pas sur...

J'ai abandonné l'idée d'utiliser new, car il n'est pas nécessaire.
J'ai remarqué que le code fonctionne en déclarant les briques (br3 et
b4) ainsi:
CBrick2d br3 = CBrick2d(0.1f ,0.2f ,0.3f ,5);
CBrick2d br4 = CBrick2d(1.5f, 2.6f, 0.1f ,0.2f ,0.3f);
au lieu de les déclarer en premier, puis de les affecter.

Mais je comprend pas pourquoi cela ne marche pas sinon.

Si vous avez eu le courage de tout lire et si vous voyez la (les)
faille(s), je vous écoute :)



Fichier Main.cpp:

#include <stdlib.h>
#include "CBrick2d.h"

int main(int argc, char *argv[])
{

CBox2d box(1.1f, 1.2f, 1.1f, 1.2f );
cout << "box: " << box << endl;
CBrick2d br3;
CBrick2d br4;

cout << "nbricks:n-------" << endl;

CBrick2d br0 = CBrick2d(box);
cout << "*** - br0 b3:n" << br0 <<endl <<endl;

br3 = CBrick2d(0.1f ,0.2f ,0.3f ,5);
cout << "*** - br3 = CBrick2d(0.1f ,0.2f ,0.3f ,5)n" <<
br3<<endl<<endl;

br4 = CBrick2d(1.5f, 2.6f, 0.1f ,0.2f ,0.3f);
cout << "*** - br4 = CBrick2d(1.5f, 2.6f, 0.1f ,0.2f ,0.3f) n" <<
br4<<endl<<endl;

br4 = br0;
cout << "*** - br4 = br0 :n" << br4 << endl <<endl;



system("PAUSE");
return 0;
}

/*

CBrick2d.h

*/
#ifndef CBRICK2D_H
#define CBRICK2D_H

#include "CBox2d.h"
// header OpenGL inclus dans CBox2d
namespace brick_const
{
const float brick_L = 1.0f;
const float brick_H = 0.4f;
const int brick_vie = 3;
const float brick_red = 0.7f;
const float brick_green = 0.8f;
const float brick_blue = 0.1f;
};

using namespace brick_const;

class CBrick2d : public CBox2d
{
private:
static unsigned long BRICK_ID; // compteur pour créer des ID
void Init(); // Initialisation par défaut


protected:

float m_red; // couleur
float m_green;
float m_blue;
int m_vie;
unsigned long m_ID;

public:


CBrick2d(const float& x, const float& y, const float& r, const float&
g, const float& b);
CBrick2d(const float& r = brick_red , const float& g = brick_green ,
const float& b = brick_blue, const int& vie = brick_vie);

CBrick2d(const CBox2d& box);

CBrick2d(const CBrick2d& brick); //recopie
virtual ~CBrick2d();

// ---------- Sets ------------
virtual void SetColor( const float& r = brick_red , const float& g brick_green , const float& b = brick_blue);
virtual void SetVie(const int& v);

// ---------- Gets ------------

virtual const float& GetRed() const;
virtual const float& GetGreen() const;
virtual const float& GetBlue() const;
virtual const int& GetVie() const;

virtual const unsigned long& GetID() const;

// ---------- operators -------------
CBrick2d& operator= (const CBrick2d& rhs);


};

ostream& operator << (ostream& flux, const CBrick2d& p);

#endif // #ifndef CBRICK2D_H

/*

CBrick2d.cpp

*/


#include "CBrick2d.h"
// -------------- Initialisation ----------
//
unsigned long CBrick2d::BRICK_ID; // initialise à 0
void CBrick2d::Init()
{
m_red = brick_red;
m_green = brick_green ;
m_blue = brick_blue;
m_vie = brick_vie;
}

// ---------- constructeurs ------------
//

CBrick2d::CBrick2d(const float& x, const float& y, const float& r,
const float& g, const float& b)
:CBox2d(x,y,x+brick_L,y+brick_H),m_red(r), m_green(g), m_blue(b)
{
m_vie = brick_vie;
m_ID = ++BRICK_ID;
// cout <<"Ctor x,y,r,g,b" <<endl;

}

CBrick2d::CBrick2d(const float& r , const float& g , const float& b ,
const int& vie )
:m_red(r), m_green(g), m_blue(b), m_vie(vie)
{
m_ID = ++BRICK_ID;
// cout <<"Ctor r,g,b,vie" <<endl;
}



CBrick2d::CBrick2d(const CBox2d& box)
: CBox2d(box)
{

Init();
m_ID = ++BRICK_ID;
// cout <<"Ctor box:" << m_ID <<endl;
}
CBrick2d::CBrick2d(const CBrick2d& brick) //recopie
: CBox2d(brick)
{

cout << "...Cbrick recopie ..";
m_red = brick.m_red; m_green = brick.m_green; m_blue = brick.m_blue;
m_vie = brick.m_vie;
m_ID = ++BRICK_ID;
}

CBrick2d::~CBrick2d() {
// cout <<"Dstor box:" << m_ID <<endl;
m_ID = 0; }

// ---------- Sets ------------
//
void CBrick2d::SetColor( const float& r , const float& g , const
float& b )
{
m_red = r; m_green = g; m_blue = b;
}
void CBrick2d::SetVie(const int& v) { m_vie =v; }


// ---------- Gets ------------
//
const float& CBrick2d::GetRed() const { return m_red; }
const float& CBrick2d::GetGreen() const { return m_green; }
const float& CBrick2d::GetBlue() const { return m_blue; }
const int& CBrick2d::GetVie() const { return m_vie; }

const unsigned long& CBrick2d::GetID() const { return m_ID; }


// ---- operators ---------------
//
CBrick2d& CBrick2d::operator= (const CBrick2d& rhs)
{
// cout << m_ID << "=op:" << rhs.m_ID <<endl;
if (m_ID == rhs.m_ID) return *this;

m_red = rhs.m_red;
m_green = rhs.m_green;
m_blue = rhs.m_blue;

m_vie = rhs.m_vie;
((CBox2d) (*this)).operator=((CBox2d)rhs);
return *this;
}



// ---------- fonctions non membres ------------
//
ostream& operator << (ostream& flux, const CBrick2d& p)
{
flux << "BrickID:" << p.GetID() << "nr:" << p.GetRed()<< ",g:" <<
p.GetGreen();
flux << ",b:" << p.GetBlue() << ",vie:"<< p.GetVie();
flux << "brickbox:n"<< (CBox2d) p;

return flux;
}

/*

CBox2d.h

*/
#ifndef CBOX2D_H
#define CBOX2D_H

#include "CPoint2d.h"

// classe de rectangles

class CBox2d
{
private:
static unsigned long BOX_ID; // compteur pour créer des ID

protected:
CPoint2d m_gb;
CPoint2d m_dh;
unsigned long m_ID;

public:

CBox2d(const float& g =0.0f , const float& b = 0.0f, const float& d 1.0f, const float& h = 0.5f);
CBox2d(const CBox2d& box); //recopie
virtual ~CBox2d();

// ---------- Sets ------------
virtual void ResetGB(const CPoint2d& p); // assigne le point gb
virtual void ResetDH(const CPoint2d& p);

// ---------- Gets ------------
virtual const CPoint2d& GetGB() const; // retrouve le Point
GaucheBas
virtual const CPoint2d& GetDH() const;


virtual const unsigned long& GetID() const;


// ---------- operators -------------
CBox2d& operator= (const CBox2d& rhs);

};

ostream& operator<< (ostream& flux, const CBox2d& p);

#endif // #ifndef CBOX2D_H

/*

CBox2d.cpp

*/

#include "CBox2d.h"

unsigned long CBox2d::BOX_ID; // initialise à 0

// ---------- constructeurs ------------
//
CBox2d::CBox2d(const float& g, const float& b, const float& d , const
float& h)
{
m_gb = CPoint2d(g, b); m_dh = CPoint2d(d, h);
m_ID = ++BOX_ID;
cout <<"BoxCtor g,b,d,h def" <<endl;
}

CBox2d::CBox2d(const CBox2d& box) //recopie
{
cout << "...Cbox recopie ..";
m_gb = box.m_gb;
m_dh = box.m_dh;
m_ID = ++BOX_ID;
}

CBox2d::~CBox2d() {
cout << "XX--DsTor CBox:" << m_ID << " --XX";
m_ID = 0;

}

// ---------- Sets ------------
//
void CBox2d::ResetGB(const CPoint2d& p) { m_gb = p; }
void CBox2d::ResetDH(const CPoint2d& p) { m_dh = p; }


// ---------- Gets ------------


// retourne les points en coin
const CPoint2d& CBox2d::GetGB() const { return m_gb; }
const CPoint2d& CBox2d::GetDH() const { return m_dh; }

const unsigned long& CBox2d::GetID() const { return m_ID; }



// ---- operators ---------------
//
CBox2d& CBox2d::operator= (const CBox2d& rhs)
{
if (m_ID == rhs.m_ID) return *this;
m_gb = rhs.m_gb;
m_dh = rhs.m_dh;
return *this;
}



// ---------- fonctions non membres ------------
//
ostream& operator << (ostream& flux, const CBox2d& p)
{
flux << "BoxID:" << p.GetID() <<",p1:" << p.GetGB()<< ",p2:" <<
p.GetDH() ;
return flux;
}

/*

CPoint2D.h

*/

#ifndef CPOINT2D_H
#define CPOINT2D_H

#include <iostream>
using namespace std;

class CPoint2d

{
private:
static unsigned long CP_ID;

protected:
float m_x;
float m_y; //
unsigned long m_ID;

public:
CPoint2d( const float& x = 0.0f, const float& y = 0.0f );
CPoint2d( const CPoint2d& p); // recopie
virtual ~CPoint2d();

// ---------- Set / Get ------------


virtual const float& GetX() const; // retrouve X
virtual const float& GetY() const;
virtual const unsigned long& GetID() const;


// ---------- operators -------------
CPoint2d& operator= (const CPoint2d& rhs);

};

ostream& operator << ( ostream& flux, const CPoint2d& p);

#endif // #ifndef CPOINT2D_H

//----------------------------------------------------------------------------
/*

CPoint2D.cpp

*/


#include "CPoint2d.h"

unsigned long CPoint2d::CP_ID; // initialise à 0

CPoint2d::CPoint2d( const float& x , const float& y )
: m_x(x),m_y(y)
{
m_ID = ++CP_ID;
// cout << "CP: construit." << m_ID<< endl;
}
CPoint2d::CPoint2d( const CPoint2d& p)
{
m_x = p.m_x; m_y = p.m_y; m_ID = ++CP_ID;
// cout << "CP: construit." << m_ID<< endl;
}
CPoint2d::~CPoint2d() { m_ID = 0; }; //destructeur

// ---------- Set / Get ------------
//

const float& CPoint2d::GetX() const { return m_x; } // retrouve X
const float& CPoint2d::GetY() const { return m_y; }
const unsigned long& CPoint2d::GetID() const { return m_ID; }


// ---- operators ----------------
//

CPoint2d& CPoint2d::operator= (const CPoint2d& rhs)
{
if (m_ID == rhs.m_ID) return *this;
m_x = rhs.m_x;
m_y = rhs.m_y;
return *this;
}
// ---------- fonctions non membres ------------
//


ostream& operator << (ostream& flux, const CPoint2d& p)
{
flux << "PointID:" << p.GetID()<<",x:" << p.GetX()<< ",y:" <<
p.GetY() ;
return flux;
}

// fin des fichiers
Avatar
dug8C
(Dug) wrote in message news:...

[snip]
Le problème est que les br3 et br4 s'initialisent avec le constructeur
par défaut alors que j'appelle explicitement un autre constructeur de
la classe de base.

Je pense que le problème vient du constructeur de recopie de CBrick2d
mais je n'en suis pas sur...

J'ai abandonné l'idée d'utiliser new, car il n'est pas nécessaire.
J'ai remarqué que le code fonctionne en déclarant les briques (br3 et
b4) ainsi:
CBrick2d br3 = CBrick2d(0.1f ,0.2f ,0.3f ,5);
CBrick2d br4 = CBrick2d(1.5f, 2.6f, 0.1f ,0.2f ,0.3f);
au lieu de les déclarer en premier, puis de les affecter.

[snip]


J'ai trouvé le pb vient de la définition de l'opérateur
d'affectation(=) de CBrick2d, je n'ai pas appellé de la classe de
base.
J'avais écris:
((CBox2d) (*this)).operator=((CBox2d)rhs);
au lieu de :
CBox2d::operator=(rhs);

Voila, j'ai des valeurs correctes maintenant.
Si vous voyez autre chose, n'hésitez pas à le dire :)

A+

Avatar
Marc Boyer
Dug wrote:
J'avais écris:
((CBox2d) (*this)).operator=((CBox2d)rhs);
au lieu de :
CBox2d::operator=(rhs);


Comme quoi, l'usage du cast "à la C" avait encore
fait une victime.
"Trust the programmer"
Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(