How to convert this VC++ 6 code to VC++ 2008? - c++

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?

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;
}

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.

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.

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.

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

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?

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.

Related

C++ User Defined Class Copy Assignment Missing?

I have written two custom classes, called A and B
My B class has a member variable a, and it has a function:
void B::setA(A s)
{
a = s;
}
However, this line is giving me an error:
'operator =' function is unavailable in 'A'.
From my understanding, this means somehow the compiler is not creating a default copy assignment function for my A class. However, I don't see why... the only constructor I've written in A looks like...
class A
{
//...
public:
A() {};
//...
};
Now in truth, A and B are large classes with a lot of member variables, and the names aren't really A and B. Short of posting the entire source for both of these classes, could anyone tell me what types of things I might look for when trying to diagnose that error message? Just to be clear, I never use pointers or low-level features like that so, as far as I know, the default copy-assignment should work fine for class A.
edit:
Someone mentioned that one of the member variables of A might be to blame, so here are all of the types:
const std::string
static const bool
static std::map<int,std::string>
std::vector
std::map<int, C>
where C is a struct that I defined in the same header file that A is in. It just contains a few integers and strings.
You have in class A a non-static data member declared as
const std::string
that is with the qualifier const. In this case the implicit copy assignment operator is defined by the compiler as deleted.
const members don't mix well with copy assignment operators. Not only won't the compiler generate one for you, it would also be semantically hard to come up with an "assignment" which does not actually assign everything.
Nothing stops you from writing an assignment operator which does not assign to your const member, of course, but that would mean one of two things:
The assigned object does not appear to the client as an identical copy of the source, which is not what one would except from a copy assignment operator, so that would be a case of operator-overloading abuse.
The member variable does not have an observable effect to the outside. In that case, one must wonder why it exists in the first place, or rather why it is not mutable rather than const.

When an object provides both `operator!` and `operator bool`, which is used in the expression `!obj`?

I've ran across a question I am not able to answer for myself. Also, I didn't find an answer to this on both google and here. Say, I want to "check an object for validity" in an if clause, like so:
MyClass myObject;
// [some code, if any]
if (!myObject)
{
// [do something]
}
Let MyClass be defined something like this:
class MyClass
{
public:
MyClass() { };
virtual ~MyClass() { };
bool operator!()
{
return !myBool;
};
operator bool()
{
return myBool;
};
private:
bool myBool = 0;
};
My question now is: Which one of the overloaded operators is actually used in this if clause? Either way, the result is obviously the same.
It will use operator!.
A function whose parameter types match the arguments will be chosen in preference to one that requires type conversions.
You'll find that operator ! gets executed because it's the most direct resolution. If it used operator bool instead then it would have to call the conversion operator first, and then apply the ! separately to that.
As a general rule, it's a good idea to avoid that situation though. It's generally better just to define the bool conversion, because strictly speaking that's what you want your logical operators to act on, rather than MyClass directly. Defining both creates a bit of a readability problem, and is a form of redundant code duplication (which can lead to programmer error in future).

C++ internals: Messing with the this-pointer

I have some questions about the internal workings of C++. I know for example that every member function of a class has an implied hidden parameter, which is the this-pointer (much in the same way Python does):
class Foo
{
Foo(const Foo& other);
};
// ... is actually...
class Foo
{
Foo(Foo* this, const Foo& other);
};
Is it wrong of me to then assume then that the validity of the function does not directly depend on the validity of this (since it's just another parameter)? I mean, sure, if you try to access a member of the this-pointer, it better be valid, but the function will otherwise continue if this is deleted, right?
For example, what if I were to mess up with the this pointer and do something like what you see below? Is this undefined behavior, or is it defined by highly discouraged? (I'm asking out of pure curiosity.)
Foo:Foo(const Foo& other)
{
delete this;
this = &other;
}
You cannot assign to this - it is of type Foo * const. You can delete this; in certain circumstances, but it's rarely a good idea.
this is defined as,
Foo(Foo* const this, ...);
Casting away the constness is not not possible for this (special case). Compiler will give errors for the same. I have asked the similar question.

c++ overloaded method in derived class

I have the following question:
Assume base class A with method:
A& operator+(A& a) {...}
I also have a derived class B which overloads (or at least it should so) this method:
A& operator+(B& b) {...}
The problem is that if i want to call something like:
b + a (where b is of type B and a of type A) i get a compile error.
(error C2679: binary '+' : no operator found which takes a right-hand operand of type 'A' (or there is no acceptable conversion)).
Shouldnt that call the base class method? (it looks like it overrides the method..)
If not, why? Is there a way to fix this (dont tell me to overload the method in B with A&)
Sorry i dont give examples in formated text, but i dont know how to format it.
Thanks in advance!
PS Im using Visual studio 2010 beta.
No, it won't call the base class function. Class B has an operator+, it doesn't take the correct parameter, end of story.
You can define operator+ as a free function, not in any class. Perhaps a friend, if it needs to access private data:
A operator+(const A &lhs, const A &rhs) { ... }
B operator+(const B &lhs, const B &rhs) { ... }
Then b + a will call the first operator, as will a + b. b + b will call the second.
Alternatively, you could "un-hide" the base class implementation, by putting this in class B:
using A::operator+;
it's probably best not to, though. Most operators work better as free functions, because then you get automatic conversions on both operands. C++ never performs conversions on the LHS of a member function call.
Btw, operator+ almost certainly should return by value, not by reference, since an automatic (stack) variable no longer exists once the function returns. So the caller needs to be passed a copy of the result, not a reference to it. For this reason operator+ and inheritance aren't a great mix, although it can probably work as long as the caller knows what they're doing.
The problem is called hiding - a member function in a derived class hides functions with the same name in the base class. In this case you can't access A::operator+(A&) because it's being hidden by B::operator+. The way to fix this is to define B::operator+(A&), and possibly have it call the base class function.
Edit: There's a section in the C++ FAQ Lite that goes into more detail about this problem and offers another possible solution, namely the using keyword.
The problem is that you are defining the member operator, so when called as b + a it results in b.operator+( a ), which doesn't exist.
Accepted practice is to define free operators that themselves would call [virtual] members on the arguments.
Edit:Standard example of what I'm talking about is adapting a class hierarchy for output streaming:
class base
{
public:
virtual ~base();
virtual void print( std::ostream& ) const;
};
std::ostream& operator<<( std::ostream& out, const base& b )
{
b.print( out ); return out;
}
This doesn't really work for math operations since you want to return by [const] value, not reference, i.e. avoid nonsense like a + b = c;.
For example, addition of real and complex numbers is defined, but yields complex number as the result, so you cannot derive complex from real. The other way - maybe. But still you want to define exact operations interface:
const real operator+( const real&, const real& );
const complex operator+( const complex&, const complex& );
Hope this gives you enough to re-think your design :)
Couple of things come to mind. First, you would generally want to make the operator + "virtual". Then, the derived operator + taking a reference to B would be an override due to co-variance, instead of hiding the base class implementation, which is what is happening here.
That said, I suspect (but can't say for certain without compiling a test project) that that would actually solve your problem. That's because the standard answer for binary operators is to use static methods that take two parameters on the class. The C++ STL uses this technique extensively, and I don't know of a reason to attempt to implement binary operators as instance methods, virtual or not. It's just too confusing, with no real up-side.

What does the const operator mean when used with a method in C++?

Given a declaration like this:
class A {
public:
void Foo() const;
};
What does it mean?
Google turns up this:
Member functions should be declared with the const keyword after them if they can operate on a const (this) object. If the function is not declared const, in can not be applied to a const object, and the compiler will give an error message.
But I find that somewhat confusing; can anyone out there put it in better terms?
Thanks.
Consider a variation of your class A.
class A {
public:
void Foo() const;
void Moo();
private:
int m_nState; // Could add mutable keyword if desired
int GetState() const { return m_nState; }
void SetState(int val) { m_nState = val; }
};
const A *A1 = new A();
A *A2 = new A();
A1->Foo(); // OK
A2->Foo(); // OK
A1->Moo(); // Error - Not allowed to call non-const function on const object instance
A2->Moo(); // OK
The const keyword on a function declaration indicates to the compiler that the function is contractually obligated not to modify the state of A. Thus you are unable to call non-const functions within A::Foo nor change the value of member variables.
To illustrate, Foo() may not invoke A::SetState as it is declared non-const, A::GetState however is ok because it is explicitly declared const. The member m_nState may not be changed either unless declared with the keyword mutable.
One example of this usage of const is for 'getter' functions to obtain the value of member variables.
#1800 Information: I forgot about mutable!
The mutable keyword instructs the compiler to accept modifications to the member variable which would otherwise cause a compiler error. It is used when the function needs to modify state but the object is considered logically consistent (constant) regardless of the modification.
This is not an answer, just a side comment. It is highly recommended to declare variables and constants const as much as possible.
This communicates your intent to users of your class (even/especially yourself).
The compiler will keep you honest to those intentions. -- i.e., it's like compiler checked documentation.
By definition, this prevents state changes you weren't expecting and can, possibly, allow you to make reasonable assumptions while in your methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
If you're using a language with static, compile time checks it's a great idea to make as much use of them as possible... it's just another kind of testing really.
Functions with const qualifier are not allowed to modify any member variables. For example:
class A
{
int x;
mutable int y;
void f() const
{
x = 1; // error
y = 1; // ok because y is mutable
}
};
C++ objects can be declared to be const:
const A obj = new A();
When an object is const, the only member functions that can be called on that object are functions declared to be const. Making an object const can be interpreted as making the object readonly. A const object cannot be changed, i.e. no data members of the object can be changed. Declaring a member function const means that the function is not allowed to make any changes to the data members of the object.
Two suggested best practices from experience:
(1) Declare const functions whenever possible. At first, I found this to be just extra work, but then I started passing my objects to functions with signatures like f(const Object& o), and suddenly the compiler barfed on a line in f such as o.GetAValue(), because I hadn't marked GetAValue as a const function. This can surprise you especially when you subclass something and don't mark your version of the virtual methods as const - in that case the compile could fail on some function you've never heard of before that was written for the base class.
(2) Avoid mutable variables when it's practical. A tempting trap can be to allow read operations to alter state, such as if you're building a "smart" object that does lazy or asynchronous i/o operations. If you can manage this with only one small mutable variable (like a bool), then, in my experience, this makes sense. However, if you find yourself marking every member variable as mutable in order to keep some operations const, you're defeating the purpose of the const keyword. What can go wrong is that a function which thinks it's not altering your class (since it only calls const methods) my invoke a bug in your code, and it could take a lot of effort to even realize this bug is in your class, since the other coder (rightly) assumes your data is const because he or she is only calling const methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
Additionally, you will easily run into problems if methods that should be const aren't! This will creep through the code as well, and make it worse and worse.
that will cause the method to not be able to alter any member variables of the object