C++ Workshop - Overloading & Data Type Conversion (Ch. 10)

Started by
31 comments, last by Dbproguy 15 years, 11 months ago
Perhaps, when we get to that chapter, we should spend some time explaining the difference between compile-time polymorphism and run-time polymorphism.
Advertisement
Thank you for the further clarification.

It's another example of the book's ambiguity and how this group is absolutely invaluable in teaching C++ because it allows such matters to be thrashed out. Another example of ambiguity that I recall is when the convention for naming pointers with an initial lower case "p" wasn't followed. It took me some time for that to click in a piece of code for me whereas I suspect that the experienced of you realised immediately what was happening!

Back to this thread - having slept on the explanations about i.increment() and ++i, I had realised that the former was a method of the class. What I hadn't appreciated was that the '++' operator called the operator++ indirectly. I thought that ++i was the normal "increment then fetch" acting on an integer. I think that if the examples in the book had been to create an object of the class Counter called "number" (for instance), rather than "i", I wouldn't have jumped into the assumption that "i" was an integer, rather than an object.
I have a question that is not chapter related, or at least not to the chapters we've read so far. Are there any guidelines on how to make comments in C++ code?

In java there is something called javadoc in which you can document methods like:
/** * This method is commented with javadoc. * @param parm A parameter to show how to document a parameter in java. * @return An int showing how to document a return type in java. */public int commentedMethod(int parm){}


Does C++ have a similar system for making comments?
No. However, Doxygen (google it) can use java-doc style comments.
Besides Doxygen, I find using (commented) header files as a sort of reference chart usefull as well. That´s personal preference however, do what you´re most comfortable with - or when at work, what the company guidelines say. ;)

As for operator overloading, think about assignment operators, like =, -= and so on. The basic type assignment operators return a reference to themselves, which makes statements like 'a = b = c = 2;' possible. Consider doing the same for your assignment operators. Also, watch out for self-assignment. I don't know if the book describes that, but hey. :)
Create-ivity - a game development blog Mouseover for more information.
Edit: This is my very late take on it. You might also want to look at some of these pages.

Quote:Original post by CondorMan
I understand the concept of overloading a function - to allow a single function name to be used several times but take different numbers or types of parameters and the compiler makes sense of which actual function to use in a particular situation, determined by it's parameters. Am I correct in thinking that this is polymorphism?


This is one form of polymorphism. There are many others.

Usually when people use the term, they are thinking of dynamic polymorphism brought-about by subtyping, which in C++ is normally done by inheritance (i.e. class Derived : public Base { /* */ }; Base* thing = new Derived(); thing->doVirtualFunction(); // calls Derived::doVirtualFunction).

Quote:The basic question I have is regarding the object (Frisky, Boots or i) - can it hold data or is it the member data element (itsAge, itsWeight) which holds the data and it is this which is accessed using the dot operator (Frisky.itsAge, Boots.itsWeight etc.)?


That sort of depends on what you think "hold data" means.

A member is *part of* the object. In memory somewhere, there is a sequence of bytes that represents a Cat (or a Counter). Some of those bytes within a Cat represent itsAge (or itsWeight). Some of those bytes within a Counter represent the counter value.

Whenever a data member is public, the outside code can access just that data member directly. When the data member is of a type that supports printing (via operator<<(ostream&, const whatever_type&) ), it could be printed that way. Out of box, all the primitive types (like 'int') support that. However, classes are types, so they can be made to support such printing - but you have to implement it (via the above-mentioned operator), so that the compiler knows how you want it done.

For example, you could support it for a Cat:

ostream& operator<<(ostream& os, const Cat& c) {  return os << "A Cat that is " << c.itsAge << " years old and weighs " << c.itsWeight << "pounds";}


And now you can 'cout << Frisky << " and " << Boots;'. :)
Quote:Also, watch out for self-assignment.


OPINION : When I see an assignment operator that has to check for self-assignment to function properly, I smell design flaws. Specifically, an assignment operator that is exception-safe is probably self-assignment safe too. Unfortunatly, you haven't got the tools yet to do it 'properly', and it's not an idiom that made any sense to me when I was first starting out. You can look up RAII and the swap-with-temp idiom if you want to get into it.
A check for self assignment can still be used for optimization, but only when a profiler tells you it counts. For example, it would be stupid for a mathmatical vector class to check for self assignment. That check is extra code that has to run for every single vector assignment, to stop a few extra copies of built in types in a very small percentage of cases.
Speaking of mathmatical vectors; like any mathmatical quantity, I would expect that, after X -= X; that X == 0. If your 'check for self assignment' breaks that condition, I wouldn't consider your vector to be correct.
Quote:Original post by Deyja
Quote:Also, watch out for self-assignment.


OPINION : When I see an assignment operator that has to check for self-assignment to function properly, I smell design flaws. Specifically, an assignment operator that is exception-safe is probably self-assignment safe too. Unfortunatly, you haven't got the tools yet to do it 'properly', and it's not an idiom that made any sense to me when I was first starting out. You can look up RAII and the swap-with-temp idiom if you want to get into it.


It's more often referred to, AFAIK, as the copy-and-swap idiom, in case you're trying to Google it.

(BTW, I agree with Deyja's opinion.)

Actually I wasn't sure it had a name. I call it the swap-with-temp (or swap-with-copy) idiom because that's how the code reads:

some_type& some_type::operator=(const some_type& rhs){    this->swap( some_type(rhs) ); //copy implemented in terms of copy constructor    return *this;}


It literally reads 'swap with a temporary'. :)
Quote:Original post by Deyja
Actually I wasn't sure it had a name. I call it the swap-with-temp (or swap-with-copy) idiom because that's how the code reads:

some_type& some_type::operator=(const some_type& rhs){    this->swap( some_type(rhs) ); //copy implemented in terms of copy constructor    return *this;}


Wouldn't this be better/more standard, as it doesn't convert the temporary to a non-const reference.
some_type& some_type::operator=(const some_type& rhs){    some_type(rhs).swap(*this); //copy implemented in terms of copy constructor    return *this;}

Arguing on the internet is like running in the Special Olympics: Even if you win, you're still retarded.[How To Ask Questions|STL Programmer's Guide|Bjarne FAQ|C++ FAQ Lite|C++ Reference|MSDN]

This topic is closed to new replies.

Advertisement