OVH Cloud OVH Cloud

Problème d'opérateur []

3 réponses
Avatar
lionel letoffet
Bonjour, voici quelques lignes extraites de mon code qui me posent problème
à l'éxecution .


// Headers
------------
class Point
{
public :
float x,y;

Point(const Point& Pt){x=Pt.x; y=Pt.y;}
Point(float valx = 0.0,float valy = 0.0){x = valx;y = valy;}
};

/ ArrayPoint
//**************************************************************************
***
class ArrayPoint : public CObject
{
protected:

float *m_X;
float *m_Y;
unsigned int m_Count;

public:
Point operator[](int nIndex) ;

virtual Point GetAt(unsigned int);

ArrayPoint(unsigned int Count,float valx, float valy);
virtual ~ArrayPoint();
};

// ArrayPoint.cpp : fichier d'implémentation
//

#include "stdafx.h"
#include "ArrayPoint.h"

ArrayPoint::ArrayPoint(unsigned int Count,float Inc)
{
m_Count=0;
m_X=NULL;
m_Y=NULL;
if(Count>0){
m_X=new float[Count];
m_Y=new float[Count];
for (int i=0;i<Count;i++){m_X[i]=(i*Inc);m_Y[i]=(i*Inc);}
m_Count=Count;
}
}

//**************************************************************************
***
ArrayPoint::~ArrayPoint()
{
if(m_X)delete[]m_X;
if(m_Y)delete[]m_Y;
}

//**************************************************************************
***
Point ArrayPoint::operator [](int Index )
{
Point pt(m_X[Index],m_Y[Index]);
return pt;
}



Tout ceci ce compile sans problème. Le souci est à l'éxecution quand dans
une application je tente d'utiliser l'opérateur []

ArrayPoint *m_Array1;
m_Array1=new ArrayPoint(1024*1024,1,1);

Point pt1;
pt1 = m_Array1[3];

Je ne peux pas compiler cette dernière ligne!!!
J'obtiens toujours l'erreur suivante :

error C2679: binary '=' : no operator found which takes a right-hand operand
of type 'ArrayPoint' (or there is no acceptable conversion)

Avez vous une idée ou une piste ???

Je suis en visual studio .NET.

Merci d'avance .

3 réponses

Avatar
kanze
lionel letoffet wrote:

// Headers
------------
class Point
{
public :
float x,y;

Point(const Point& Pt){x=Pt.x; y=Pt.y;}
Point(float valx = 0.0,float valy = 0.0){x = valx;y = valy;}
};

/ ArrayPoint

//**************************************************************************

***
class ArrayPoint : public CObject


Est-ce qu'il y a une raison pour l'héritage de CObject ? J'ai
l'impression que ta classe a la sémantique d'une collection, et
en général (mais il y a des exceptions), les collections en C++
n'héritent de rien.

{
protected:


protected ? Et il y a des données qui suivent ? Je me serais
attendu à private.

float *m_X;
float *m_Y;


Et pourquoi pas simplement Point* ?

unsigned int m_Count;

public:
Point operator[](int nIndex) ;


Habituellement, il y a deux operator[], l'un const, et l'autre
non. S'il y en a un qui renvoie un objet (et non une référence),
c'est celui qui est const.

virtual Point GetAt(unsigned int);


Pourquoi virtuel ? Quelle est la différence entre l'operator[]
et la fonction GetAt ? Pourquoi est-ce que l'un prend un int, et
l'autre un unsigned ? Pourquoi est-ce que l'un est virtuel, et
l'autre non ?

ArrayPoint(unsigned int Count,float valx, float valy);
virtual ~ArrayPoint();
};

// ArrayPoint.cpp : fichier d'implémentation
//

#include "stdafx.h"
#include "ArrayPoint.h"

ArrayPoint::ArrayPoint(unsigned int Count,float Inc)
{
m_Count=0;
m_X=NULL;
m_Y=NULL;
if(Count>0){
m_X=new float[Count];
m_Y=new float[Count];
for (int i=0;i<Count;i++){m_X[i]=(i*Inc);m_Y[i]=(i*Inc);}
m_Count=Count;
}
}


En général, on préfère les initialisateurs, du genre :

ArrayPoint::ArrayPoint(
unsigned count,
float increment )
: m_X( count > 0 ? new float[ count ] : NULL )
, m_Y( count > 0 ? new float[ count ] : NULL )
, m_count( count )
{
for ( unsigned i = 0 ; i < m_count ; ++ i ) {
m_X[ i ] = i * increment ;
m_Y[ i ] = i * increment ;
}
}

Mais ça ne fait que réprendre ta logique ; il reste plusieurs
problèmes ?

-- D'abord, pourquoi traiter count == 0 à part. On a
parfaitement droit à faire un new de 0 octets, pourvu qu'on
ne déréférence jamais le pointeur qu'il renvoie.

-- Mais surtout, évidemment, le code est incorrect. C'est assez
difficile à écrire un constructeur qui fait deux allocations
sans l'utilisation des pointeurs intelligents -- à ta place,
par exemple, des boost::scoped_array ferait bien l'affaire ;
un seul new Point[ count ] me semble encore beaucoup mieux,
et un std::vector< Point > idéal (en supposant que le but de
la manip est autre que d'apprendre comment écrire des
collections, évidemment).

Si c'était moi, je n'aurais qu'une seule variable membre :

std::vector< Point > m_data ;

et le constructeur serait simplement :

ArrayPoint::ArrayPoint(
unsigned count,
float increment )
{
m_data.reserve( count ) ;
for ( unsigned i = 0 ; i < count ; ++ i ) {
m_data.push_back( Point( i * increment, i * increment ) ) ;
}
}



//**************************************************************************

***
ArrayPoint::~ArrayPoint()
{
if(m_X)delete[]m_X;
if(m_Y)delete[]m_Y;
}


Les if ne sont pas nécessaire ; delete est bien défini sur un
pointeur nul.


//**************************************************************************

***
Point ArrayPoint::operator [](int Index )
{
Point pt(m_X[Index],m_Y[Index]);
return pt;
}


Et comment tu utilises l'opérateur sur la côté gauche d'une
affectation ? J'aurais vu plutôt deux opérateurs :

Point // ou : Point const&
ArrayPoint::operator[](
unsigned index ) const
{
assert( index < m_data.size() ) ;
return m_data[ index ] ;
}

Point&
ArrayPoint::operator[](
unsigned index )
{
assert( index < m_data.size() ) ;
return m_data[ index ] ;
}

Tout ceci ce compile sans problème. Le souci est à l'éxecution
quand dans une application je tente d'utiliser l'opérateur []

ArrayPoint *m_Array1;
m_Array1=new ArrayPoint(1024*1024,1,1);


Pourquoi le pointeur et l'allocation ? Pourquoi simplement :

ArrayPoint array( 1024*1024, 1, 1 ) ;

Point pt1;
pt1 = m_Array1[3];

Je ne peux pas compiler cette dernière ligne!!!


Évidemment, puisque m_Array est un pointeur, et non un
ArrayPoint. (*m_Array)[ 3 ] ferait l'affaire, mais typiquement,
c'est assez rare d'avoir besoin des pointeurs à des
collections ; les pointeurs servent surtout pour des objets
entités (et évidemment, dans l'implémentation des collections,
et d'autres utilisation de bas niveau).

J'obtiens toujours l'erreur suivante :

error C2679: binary '=' : no operator found which takes a
right-hand operand of type 'ArrayPoint' (or there is no
acceptable conversion)


En effet, le message d'erreur pourrait mener à confusion, parce
que pour des raisons histér^H^Horique, les pointeurs en C++
acceptent les opérateurs [] aussi -- ce que tu as écrit, c'est
l'équivalent de *(m_Array + 3). Qui serait un ArrayPoint (et non
un Point), sauf que tu n'en as alloué qu'un, et donc, l'objet
n'existe pas.

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

Avatar
Ahmed MOHAMED ALI
Bonjour,
m_Array1 est un pointeur sur ArrayPoint.Pour accéder à l'opérateur
d'indiçage,il faut le déréférencer afin de récupérer l'objet sur lequel il
pointe.
m_Array1[3] est un pointeur sur le quatrième élément d'un tableau de
ArrayPoint ,pour qui de plus de la mémoire n'est pas allouée.

Pour corriger ton problème:

ArrayPoint m_Array1(1024*1024,1,1);
pt1 = m_Array1[3];

ou bien

ArrayPoint *m_Array1;
m_Array1=new ArrayPoint(1024*1024,1,1);
pt1 = (*m_Array1)[3];

Cordialement,
Ahmed MOHAMED ALI





"lionel letoffet" wrote in message
news:422d5308$0$309$
Bonjour, voici quelques lignes extraites de mon code qui me posent
problème

à l'éxecution .


// Headers
------------
class Point
{
public :
float x,y;

Point(const Point& Pt){x=Pt.x; y=Pt.y;}
Point(float valx = 0.0,float valy = 0.0){x = valx;y = valy;}
};

/ ArrayPoint

//**************************************************************************

***
class ArrayPoint : public CObject
{
protected:

float *m_X;
float *m_Y;
unsigned int m_Count;

public:
Point operator[](int nIndex) ;

virtual Point GetAt(unsigned int);

ArrayPoint(unsigned int Count,float valx, float valy);
virtual ~ArrayPoint();
};

// ArrayPoint.cpp : fichier d'implémentation
//

#include "stdafx.h"
#include "ArrayPoint.h"

ArrayPoint::ArrayPoint(unsigned int Count,float Inc)
{
m_Count=0;
m_X=NULL;
m_Y=NULL;
if(Count>0){
m_X=new float[Count];
m_Y=new float[Count];
for (int i=0;i<Count;i++){m_X[i]=(i*Inc);m_Y[i]=(i*Inc);}
m_Count=Count;
}
}


//**************************************************************************

***
ArrayPoint::~ArrayPoint()
{
if(m_X)delete[]m_X;
if(m_Y)delete[]m_Y;
}


//**************************************************************************

***
Point ArrayPoint::operator [](int Index )
{
Point pt(m_X[Index],m_Y[Index]);
return pt;
}



Tout ceci ce compile sans problème. Le souci est à l'éxecution quand dans
une application je tente d'utiliser l'opérateur []

ArrayPoint *m_Array1;
m_Array1=new ArrayPoint(1024*1024,1,1);

Point pt1;
pt1 = m_Array1[3];

Je ne peux pas compiler cette dernière ligne!!!
J'obtiens toujours l'erreur suivante :

error C2679: binary '=' : no operator found which takes a right-hand
operand

of type 'ArrayPoint' (or there is no acceptable conversion)

Avez vous une idée ou une piste ???

Je suis en visual studio .NET.

Merci d'avance .




Avatar
lionel letoffet
OK j'ai compris .
il fallait déréférencer le pointeur !!


Point pt1;
pt1 = *(m_Array1)[3];


"lionel letoffet" a écrit dans le message de
news:422d5308$0$309$
Bonjour, voici quelques lignes extraites de mon code qui me posent
problème

à l'éxecution .


// Headers
------------
class Point
{
public :
float x,y;

Point(const Point& Pt){x=Pt.x; y=Pt.y;}
Point(float valx = 0.0,float valy = 0.0){x = valx;y = valy;}
};

/ ArrayPoint

//**************************************************************************

***
class ArrayPoint : public CObject
{
protected:

float *m_X;
float *m_Y;
unsigned int m_Count;

public:
Point operator[](int nIndex) ;

virtual Point GetAt(unsigned int);

ArrayPoint(unsigned int Count,float valx, float valy);
virtual ~ArrayPoint();
};

// ArrayPoint.cpp : fichier d'implémentation
//

#include "stdafx.h"
#include "ArrayPoint.h"

ArrayPoint::ArrayPoint(unsigned int Count,float Inc)
{
m_Count=0;
m_X=NULL;
m_Y=NULL;
if(Count>0){
m_X=new float[Count];
m_Y=new float[Count];
for (int i=0;i<Count;i++){m_X[i]=(i*Inc);m_Y[i]=(i*Inc);}
m_Count=Count;
}
}


//**************************************************************************

***
ArrayPoint::~ArrayPoint()
{
if(m_X)delete[]m_X;
if(m_Y)delete[]m_Y;
}


//**************************************************************************

***
Point ArrayPoint::operator [](int Index )
{
Point pt(m_X[Index],m_Y[Index]);
return pt;
}



Tout ceci ce compile sans problème. Le souci est à l'éxecution quand dans
une application je tente d'utiliser l'opérateur []

ArrayPoint *m_Array1;
m_Array1=new ArrayPoint(1024*1024,1,1);

Point pt1;
pt1 = m_Array1[3];

Je ne peux pas compiler cette dernière ligne!!!
J'obtiens toujours l'erreur suivante :

error C2679: binary '=' : no operator found which takes a right-hand
operand

of type 'ArrayPoint' (or there is no acceptable conversion)

Avez vous une idée ou une piste ???

Je suis en visual studio .NET.

Merci d'avance .