Re: help: class compile error

From: xuatla (xuatla_at_gmail.com)
Date: 07/09/04


Date: Fri, 09 Jul 2004 13:56:14 -0700
To: "Victor Bazarov <v.Abazarov@comAcast.net>;John Harrison" <john_andronicus@hotmail.com>

Great. Thanks Victor Bazarov and John Harrison for the detail and
comprehensive explanation.

I corrected the code in your ways and now it goes through successfully.

I have some more questions about your answer.
>> CTest::CTest( const int &size )
>> {
>> iSize = size;
>> dElement = new double[iSize];
>
>
> Always prefer initialization over assignment. Read the FAQ.

What does this mean? Can I do the initialization and assignment in other
way? Where can I get FAQ? Can you tell me how to get the "help" file for
c++ grammar. Not man g++ but the grammar help of c++. I mean the on disk
help.

>
>> for ( int i = 0; i < iSize; i++ ) dElement[i] = 0.0;
>> }
>>

>> // copy operator
>> CTest CTest::operator = ( CTest &t2 )
>> { // <======== line 49
>> if ( iSize != t2.size() ) // reallocate the memory
>
>
> What if it's smaller? Is there still the need to reallocate?

If the size is smaller, then I can just change iSize but leave the
dElement unchanged. But what I concern is that if I don't release
dElement and reallocate it, then it may waste the memory. For example,
suppose
   t1 = t2; //t1.size() = 100, t2.size() = 2;
then t1.dElement still occupies 100 double. Is it correct?

I designed this class because I am not familiar with "vector" in C++ and
I need to use this type frequently. In my code it's rare that the size
is decreased.

>
>> {
>> iSize = t2.size();
>> if (dElement) delete [] dElement;
You mentioned that I dont need to judge whether dElement is NULL before
deleting it. Is true for all types pointer?

>> dElement = new double[iSize];
>> }
>>
>> for ( int i = 0; i < iSize; i++ ) dElement[i] = t2[i];
Now I know that I need to use t2.dElement[i] instead of t2[i] here. If I
use t2[i], then compile error: no operator [] for const CTest&.

>
>

if I use #include "iostream.h", then compiler will give the warning of
"deprecated or antiquated header". But it's just a warning and compile
still completed. I changed to the following as you suggested.

#include <iostream>
using namespace std;

Do I need to add "using namespace" always for such a head file usage?

Another question for the class. I tried to use "const CTest&" but failed
and was told I didn't define the const class type (now I learned from
your explanation). Then I tried the following
class CTest
{
  .....
} const;

What's the meaning of such "const" class?

One more question about new and delete:

I use new to create a CTest. And then delete it. But it seems that the
deletion is not successful. When I print it, it's still there.

Do I need to define new and delete for class by myself?

// main function
int main(void)
{
        int N = 10;
        CTest t1(N);
        int i;

        for ( i = 0; i < N; i++ ) t1[i] = i;
        
        CTest *t2 = new CTest;

        *t2 = t1;
        
        for ( i = 0; i < N; i++ ) cout << (t1+*t2)[i] << endl;

        delete t2;

        for ( i = 0; i < N; i++ ) cout << (*t2)[i] << endl;
                // still print out t2.

        return 1;
}

Thanks a lot for your kind help!

X

Victor Bazarov wrote:
> xuatla wrote:
>
>> I encountered the following compile error of c++ and hope to get your
>> help.
>>
>> test2.cpp: In member function `CTest CTest::operator+=(CTest&)':
>> test2.cpp:79: error: no match for 'operator=' in '*this =
>> CTest::operator+(CTest&)((+t2))'
>> test2.cpp:49: error: candidates are: CTest CTest::operator=(CTest&)
>> make: *** [test2.o] Error 1
>>
>> I don't know why in the main function, "t2 = t1" is ok, but in the
>> operator += body, "*this = *this+t2" is wrong. What I am thinking is
>> that the compiler looks for *this+t2 first, which generate a new CTest
>> instance, and then copy to *this. What's the mistake I made?
>>
>> The code is compiled succeedly in Visual C++. but not in linux g++
>> (3.3.3).
>>
>> And also in Visual C++,
>> for ( int i = 0; ... ;.... )
>> defines a global int i. so I can use
>> for ( int i = 0; ... ;.... ) { ... }
>> for ( i = 0; ...;......) { ... }
>> but in linux g++, this is wrong. "i" is only alive in the for body. I
>> need to define "i" again in the 2nd for body. What's the update of
>> this grammar? Which one is the standard c++?
>
>
> If a variable is declared in the for statement, its scope is limited
> to the for statement and its body. VC++ has it as "an extension",
> otherwise known as the "for scope bug".
>
>>
>> Thank you very much in advance for the help.
>>
>> X
>>
>> -----------------------------------------------------
>> source code below:
>>
>> #include <iostream.h>
>
>
> There is no such standard header. Use <iostream>
>
>>
>> class CTest
>> {
>> private:
>> int iSize;
>> double *dElement;
>>
>> public:
>> CTest( const int &size = 1);
>
>
> Integers and other built-in types are usually better passed by
> value. It's much simpler to understand:
>
> CTest(int size = 1);
>
>> CTest( CTest &t );
>
>
> Copy constructors _usually_ accept their arguments by a _const_
> reference, unless they somehow _change_ the arguments.
>
>
> CTest(CTest const&);
>
>> ~CTest();
>>
>> public:
>> CTest operator = ( CTest &t2 );
>
>
> The _conventional_ operator= should return a _reference_ and also
> take its argument by a _const_ reference (unless it intends to change
> it somehow).
>
> CTest& operator=(CTest const &);
>
>> const int size(void) { return iSize; }
>
>
> Return value's cv-qualifiers are usually meaningless (and are not
> used anyway). A member function that doesn't (and never should)
> change its object should be declared 'const':
>
> int size() const { return iSize; }
>
>> double &operator[]( const int &index ) { return dElement[index]; }
>
>
> Again, passing a built-in type by reference is unnecessary:
>
> double& operator[](int index) { return dElement[index]; }
>
>>
>> public:
>> CTest operator + ( CTest &t2 );
>
>
> Any operator that doesn't change its operands should take those
> operands as 'const':
>
> CTest operator +(CTest const& t2) const;
>
>> CTest operator += ( CTest &t2 );
>
>
> Assignment operators _usually_ return a reference and if argument
> is not intended to be changed, it should be const:
>
> CTest& operator += (CTest const &t2);
>
>> };
>>
>> // constrution
>> CTest::CTest( const int &size )
>> {
>> iSize = size;
>> dElement = new double[iSize];
>
>
> Always prefer initialisation over assignment. Read the FAQ.
>
>> for ( int i = 0; i < iSize; i++ ) dElement[i] = 0.0;
>> }
>>
>> // copy constrution
>> CTest::CTest( CTest &t2 )
>
>
> See above about the change in the signature.
>
>> {
>> iSize = t2.size();
>> dElement = new double[iSize];
>
>
> Same here -- initialise, not assign.
>
>> for ( int i = 0; i < iSize; i++ ) dElement[i] = t2[i];
>
>
> You have full access to 't2's contents, why make additional calls
> to the operator[] here, when you simply could do
>
> ....... dElement[i] = t2.dElement[i];
>
> ?
>
>> }
>>
>> // destruction: release the allocated memory
>> CTest::~CTest()
>> {
>> if (dElement) delete[] dElement;
>
>
> No need to check for 'dElement's non-NULL-ness, just delete[].
> Deleting a null pointer has no effect.
>
>> }
>>
>> // copy operator
>> CTest CTest::operator = ( CTest &t2 )
>> { // <======== line 49
>> if ( iSize != t2.size() ) // reallocate the memory
>
>
> What if it's smaller? Is there still the need to reallocate?
>
>> {
>> iSize = t2.size();
>> if (dElement) delete [] dElement;
>> dElement = new double[iSize];
>> }
>>
>> for ( int i = 0; i < iSize; i++ ) dElement[i] = t2[i];
>
>
> Again, you can access t2.dElement directly, no need to call the
> operator[] for t2.
>
>> return *this;
>> }
>>
>> CTest CTest::operator + ( CTest &t2 )
>
>
> The type of function should change and the type of its argument.
> See above.
>
>> {
>> if ( iSize != t2.size() )
>> { // errorhandle
>> return *this; // to be changed
>> }
>>
>> CTest sum(t2);
>>
>> for ( int i = 0; i < iSize; i++ ) sum[i] += dElement[i];
>
>
> Again, you could simply access sum.dElement directly here.
>
>>
>> return sum;
>> }
>>
>> CTest CTest::operator += ( CTest &t2 )
>
>
> The return value type should change and the argument type. See
> above.
>
>> {
>> *this = *this + t2; // <===== line 79. compile error
>>
>> return *this;
>> }
>>
>> // main function
>> main(void)
>
>
> There are no implicit return types in C++.
>
> int main()
>
>> {
>> int N = 10; CTest t1(N);
>>
>> for ( int i = 0; i < N; i++ ) t1[i] = i;
>> CTest t2;
>>
>> t2 = t1;
>> for ( int i = 0; i < N; i++ ) cout << (t1+t2)[i] << endl;
>> return 1;
>> }
>
>
> Fix it all up as I recommend and see if the error goes away.
>
> Victor



Relevant Pages

  • Re: weird error
    ... Victor Bazarov wrote: ... (These error messages sure ... > Your 'const' is all screwed up again. ... > non-const SomeClass object. ...
    (comp.lang.cpp)
  • Re: Volatile
    ... > Victor Bazarov wrote: ... > const and volatile can appear in many places with types, modifiers, ... > typedef const int constint; ... When you use it in a declaration, ...
    (comp.lang.cpp)
  • Re: template specialization problem, but only with char*
    ... Victor Bazarov wrote: ... > Adam wrote: ... > 'const' relates to the object, ... typedef char* Char; ...
    (comp.lang.cpp)
  • Re: Ping using VBS w/o active window
    ... 'function returns TRUE if successful contact was made. ... Dim oWMI,oRef ... Const ReturnImmediately=&h10 ... Exit Function ...
    (microsoft.public.scripting.vbscript)
  • Re: vector of vectors
    ... "Victor Bazarov" wrote in message ... it's better to use a const reference... ... >> not at namespace scope. ...
    (comp.lang.cpp)