views:

638

answers:

7

Forgive me my C++ is incredibly rusty. But I am trying to take some old code and recompile it under Visual C++ 2008. It was originally written for Visual C++ 6.0

The error I am getting is this:

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

Ok seems simple enough. But then I look at the offending line of code:

operator=(int i) {SetAsInt(i);};

And it appears the type IS declared. So what am I missing?

FOLLOW UP:

I took Micheals advice and added a return type of the function (the class), and added return this; to the end of each. Then I ran across this:

operator=(const CString& str);

There is no function body defined... what exactly does this mean?

+7  A: 

You need to have the operator=() method return something (it would assume int if the diagnostic weren't an error, as the error message somewhat confusingly indicates).

Generally it would be a reference to the object the operator is working on so the assignments can be chained as in a normal assignment expression. Something like:

// where T is the class for this operator= implementation

T& operator=( int i) {
     // ...
    return *this;
}
Michael Burr
Artyom
It could return a const` chaining.
Michael Burr
"And returning a const
Artyom
Michael Burr
Michael Burr
+3  A: 

As michael has said, operator= needs a return type, but this type can be void:

class A {
   ...  
   void operator = ( int i ) {
      SetAsInt(i);
   }
};

although this means you won't be able to "daisy-chain" assignments.

Regarding the follow-up, it's probably saying that assignment for the class is forbidden:

class B {
    private:
        void operator =( const B & );    
};

Making the assignment op (and usually the copy ctor) private and then not implementing them means it is impossible to assign (or copy) class instances, which is desirable behaviour for most business -oriented classes.

anon
+2  A: 

For your second question, the declaration is likey being used to prevent copying the object.

From the C++ Reference Guide by Danny Kalev

Question: How Can I Prevent Object-Copying?

Answer: Declare the copy constructor and the assignment operator as private members, without defining them. Any statement that involves direct or indirect copying of that class will cause a compilation error. This technique isn’t exactly the picture of elegance, but in contemporary C++ there’s no other way to block copying inexpensively.

Michael Burr
OK that sheds some light on it. They never mentioned this in my college years of C++.
Neil N
+2  A: 

Regarding your edit: It simply means that the function has been declared, but not defined. The compiler knows it exists, so it is legal to call it. But it will generate a linker error, unless the compiler is actually able to find the body somewhere.

Typically, you define the function in a header file, and then in the .cpp file, you have something like

// Assuming the class it is a member of is called Foo
Foo& Foo::operator=(const CString& str) {
 ...
}

The only thing to note here is the Foo:: prefix. Because this definition is outside the class definition itself, we have to use this prefix to specify that the operator= we're defining belongs to the Foo class.

jalf
Ok I found the funciton body. Though I never understoof why C++ had this weird idea of declararions in one place and definitions in another.
Neil N
Good catch, jalf. This explanation never crossed my mind to discuss as it's how most C++ methods are defined. However, I agree with you Neil that having a single place for declarations/definitions (like Java/C#) is much more intuitive.
Michael Burr
Because that way you can #include the file containing the declaration only, and you're able to call the function, without the compiler having to parse the entire function body again. In the 70's, when C was designed, this was a simple way to speed up compile-times.
jalf
30-40 years ago, compilers couldn't justify the cost of keeping the entire file in memory like a Java/C# compiler does. It had to scan the file sequentially, and so things had to be kept simple. Today, it's an awkward, error-prone and inefficient mechanism. But it made sense back then. ;)
jalf
+1  A: 

Well, that's an assignment operator. It helps one define how other objects (both of the same and other types) are assigned to an instance of the class it is defined within.

The correct syntax is (assuming your class is called 'Object'):

const Object& operator=(const Object& other)
{
  // copy members, one at a time.
  this->member1 = other.member1;
  return *this;
}

Notice the return type is constant. This is a to avoid semantically incorrect, syntactically correct statements such as:

Object A, B, C;

(A = B) = C;

If you define the return type as constant, the above code will not compile (reasonable enough, since it's really messed up) while leaving out the const will allow such bad code to compile, and of course someone will pull their hair trying to figure out what's wrong.

P.S. You might want to think it through: what would happen if you leave out the const from the return type and execute the (A = B) = C; code?

Ash
+1  A: 

Regarding the follow-up question, the return type can be anything in this case. However, since most assignment operators return a reference to the class in which they are declared, it would be best to return just that, in order not to confuse the reader.

CString& operator=(const CString& str);

Presumably, this function is declared in the private section of the class. This is the standard idiom to make objects of the class non-assignable.

avakar
+1  A: 

returning ANYTHING but an lval is typically wrong and is only used in very special situations

certainly returning a const reference precludes assignment chaining (a=(b=c)), and part of the point of operators is to make classes behave like built in types

pgast