GIDForums  

Go Back   GIDForums > Computer Programming Forums > CPP / C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 04-Sep-2007, 23:35
transfrank transfrank is offline
Junior Member
 
Join Date: Aug 2007
Posts: 53
transfrank is on a distinguished road

custom array class: operator[] not working for new dynamic allocation


Hello,
I created an array class called floatArrayFrank that replaces the C float array. I initialize it with the quantity of floats it containts.
My floatArrayFrank class works fine when I allocate it on the stack, but if I do an allocation on the stack with new
the operator[] does not compile properly. The rest of my program requires that I can reallocate as needed.
CPP / C++ / C Code:
floatArrayFrank *a;
float b;
a = new floatArrayFrank(40); /*initialize arrayClass to contain 40 floats*/
a[10]= 3.14/*run time error. IS THE COMPILER THINKING OF 10 TH ELMENT OF ARRAY OF CLASSES? I DID NOT USE NEW[].*/
b = a[10]; /* COMPILER  ERROR: binary '=' no operator defined which takes a right hand operand
	of type 'class floatArrayFrank' (or there is no acceptable conversion*/

floatArrayFrank c(40); /*allocation on stack*/
float d;
c[10]=3.14; /*works fine*/
d=c[10]; /*works fine, BUT EXPECTING 'RETURN A VALUE' CLASS MEMBER TO BE CALLED*/


What can I do to fix this? I include my class.
Thanks,
Frank
CPP / C++ / C Code:

class floatArrayFrank 
{

public:
  int getSize()const;
  floatArrayFrank(int size);
  ~floatArrayFrank();
  float & operator[](int i);
  float operator[](int i) const;
  floatArrayFrank & operator=(const floatArrayFrank &rhs);
private:
  int itsArraySize;
  float *itsArray;  
};


int floatArrayFrank::getSize()const 
{
  return itsArraySize;
}

floatArrayFrank::floatArrayFrank(int size) 
{
  /*CONSTRUCTOR*/
	int i;
	if (size<1)
	{
		std::cout <<"ERROR:integerArrayFrank does not allow null or negative sizes.\n";
		exit(-1);
	}
	
	itsArray     = new float[size];
	itsArraySize = size;
	for (i=0; i<size; i++)
		itsArray[i]=0;
}

floatArrayFrank::~floatArrayFrank() 
{
  /*DESTRUCTOR*/
	delete [] itsArray;
}

float & floatArrayFrank::operator[](int i) 
{
/*OPERATOR[] RETURNS MODIFIABLE L VALUE   EX: INSTANCE[i]=123   */
	if ( (i>(itsArraySize-1)) || (i<0) )
	{
		std::cout << "ERROR in integerArrayFrank. Attempt to access past size\n";
		exit(-1);
	}
	else
	{
		std::cout << "float & floatArrayFrank::operator[](int i) : RETURN REFERENCE\n";
		return itsArray[i]; /*RETURN REFERENCE. */
	}
}

float  floatArrayFrank::operator[](int i) const
{
/*OPERATOR[] RETURNS RVALUE  EX: A=INSTANCE[10]*/
	if ( (i>(itsArraySize-1)) || (i<0) )
	{
		std::cout << "ERROR in integerArrayFrank. Attempt to access past size\n";
		exit(-1);
	}
	else
	{
		std::cout << "floatArrayFrank::operator[](int i) const: RETURN A VALUE\n";
		return itsArray[i]; /*RETURN A COPY*/
	}
}

floatArrayFrank & floatArrayFrank::operator=(const floatArrayFrank &rhs) 
{
  /*COPY CONSTRUCTOR*/
	int i;
	if (this == &rhs)
		return *this;
	
	delete [] itsArray;
	itsArraySize=rhs.getSize();
	itsArray = new float[itsArraySize];
	for (i=0; i<itsArraySize; i++)
		itsArray[i]=rhs.itsArray[i];
	
	return *this;
}


  #2  
Old 05-Sep-2007, 11:48
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,620
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: custom array class: operator[] not working for new dynamic allocation


Quote:
Originally Posted by transfrank
Hello,
I created an array class

I won't get into the details of program design and certain no-nos of your code. In other words, I won't try to debug the class itself. I will point out a few technical errors that you need to overcome before you get to the "good stuff".

(First of all, the statement a[10]= 3.14 is missing a semicolon, but I assume that you didn't have that particular error in your actual test code.)

Anyhow:

CPP / C++ / C Code:
    floatArrayFrank *a;
    /*initialize arrayClass to contain 40 floats*/
    a = new floatArrayFrank(40);

The comment is correct. These statements declare a single object and initialize it with itsArraySize = 40. The variable a is a pointer whose value is the address of the newly created object.


However, the following statement:
CPP / C++ / C Code:
    a[10]= 3.14;

Tries to assign a floating point value to the 10th element of an array of floatArrayFrank objects.

In C and C++, there is a very fundamental notation definition. The following is always true:

If x is a pointer data type and n is an integer data type then the following two notations are semantically identical

x[n] is exactly the same as *(x + n).

And I mean exactly. Not usually always. Not almost the same as. Exactly.

Therefore, since a is a pointer, and 10 is an integer, the code is trying to make an assignment to the 10th element of an array.

(The compiler only knows that you declared a to be a pointer. It does not keep track of the nature of your declaration, which only allocated memory for one object. It doesn't work that way.) This can produce a run-time error, since you are accessing memory that doesn't belong to you.

Going on to the next statement:
CPP / C++ / C Code:
    b = a[10];
Now, maybe you can understand the compiler message, right? The right-hand side is an object; the compiler takes it to mean the 10th element of an array of floatArrayFrank objects (although accessing it would be illegal), and the left-hand side is a float. Since you haven't created an overloaded assignment operator that would make this legal, the compiler bails out at this point. (If you had created such an operator, it could compile this statement, but since you would be accessing memory that you don't own, it could generate a run-time error.)

If you really want one object, and you create it the way that you did a, then, since a is a pointer, you must dereference it in order to access the object itself.

So, we could have:
CPP / C++ / C Code:
    floatArrayFrank *a;
    float b;
    a = new floatArrayFrank(40);
    (*a)[10]= 3.14;
    b = (*a)[10];
    cout << "b = " << b << endl;

See footnote
And you might see:
Code:
float & floatArrayFrank::operator[](int i) : RETURN REFERENCE float & floatArrayFrank::operator[](int i) : RETURN REFERENCE cout << "b = " << b << endl;

So, both of the assignment statements now use the [] operator.

And for the rest of the program:
CPP / C++ / C Code:
    floatArrayFrank c(40);
    float d;
    c[10]=3.14;
    d=c[10];
    cout << "d = " << d << endl;

Now the results are the same with d as they were with *a


As far as the [] operators, the one that you have returning a value doesn't make sense to me.

Maybe you have seen things like:
CPP / C++ / C Code:
const float & floatArrayFrank::operator[](int i) const

These would be used to allow the [] operator to work with const objects.

One final note:

Your so-called "copy constructor" is not a copy constructor. It is an overloaded assignment operator. You don't have a copy constructor. A copy constructor is declared like any other constructor (just the class name; no return type). The argument of a copy constructor is a reference to an object of the class.

A copy constructor would be invoked by something like
CPP / C++ / C Code:
    floatArrayFrank c(40); // construct with int argument
.
.    // do stuff with c
.
    floatArrayFrank(c); // copy constructor

(And if you don't create a copy constructor, then the last statement uses the default copy constructor --- with a "shallow" copy. That is probably fatal at run time for your class.)


Regards,

Dave

Footnote: Consistent with what I said about equivalence of pointer and index notation, you could access the element with
a[0][10], and the result would be exactly the same as (*a)[10]
Last edited by davekw7x : 05-Sep-2007 at 12:28.
  #3  
Old 06-Sep-2007, 14:28
transfrank transfrank is offline
Junior Member
 
Join Date: Aug 2007
Posts: 53
transfrank is on a distinguished road

Re: custom array class: operator[] not working for new dynamic allocation


Thanks a lot for your input!

Yes, the big fix was to do (*a)[10]. I tried to improvise with all kinds of erroneous variants
like a->[10]. Your a[0][10] suggestion is pretty cool too.

Thanks also for pointing to me that I labeled wrongly the assignment operator and have no copy constructor.
Of course thinking I had one when I did not, thus allowing the default shallow copy. You found a big programming error, thanks!

>Maybe you have seen things like:
>const float & floatArrayFrank:perator[](int i) const
>These would be used to allow the [] operator to work with const objects.

Would I need this only if I chain two functions, like below?

CPP / C++ / C Code:
int foo1( const flloat a1); /*DECLARATION*/

floatArrayFrank *a = floatArrayFrank(50);
int h;

(*a)[10]=3.14;
h=foo1 ((*a)[10]);


Best regards,
Frank
  #4  
Old 06-Sep-2007, 15:34
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,620
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: custom array class: operator[] not working for new dynamic allocation


[quote=transfrank]
Quote:
Originally Posted by davekw7x
CPP / C++ / C Code:
const float & floatArrayFrank::operator[](int i) const
These would be used to allow the [] operator to work with const objects.
Quote:
Originally Posted by transfrank
Would I need this only if I chain two functions, like below?
The idea is that it could be used with const objects (if you had some kind of way of creating a const object ... that is, a way of initializing the object's data members).
CPP / C++ / C Code:
    const floatArrayFrank z(20); // but you have to have some kind of initializer for the values
    floatArrayFrank d;
.
.
.
    d = z[10];

May not be useful for your class, but that's the idea.

Regards,

Dave
 

Recent GIDBlogLast Week of IA Training by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Hard drive/CPU Diagnoses Issues binarybug Computer Hardware Forum 1 22-Jan-2007 19:23
polynomial class can't return a full dynamic array JKSung5295 CPP / C++ Forum 2 13-Oct-2006 00:19
Need help deleting the last element in the array headphone69 CPP / C++ Forum 2 15-Mar-2006 19:31
Pointer Usage in C++: Beginner to Advanced varunhome CPP / C++ Forum 0 19-Aug-2005 09:25
template comiling problems - need expert debugger! crq CPP / C++ Forum 1 01-Feb-2005 21:26

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 14:46.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.