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

Started by
31 comments, last by Dbproguy 15 years, 11 months ago

Welcome to the GDNet C++ Workshop – Ch. 10

For a complete introduction to this workshop, please look here. Workshop Overview This workshop is designed to aid people in their journey to learn beginning C++. This workshop is targeted at highly motivated individuals who are interested in learning C++ or who have attempted to learn C++ in the past, but found that without sufficient support and mentoring they were unable to connect all the pieces of this highly complex but powerful programming language. This is a 'guided' self-teaching C++ workshop. Each student is responsible for taking the time to read the material and learn the information. The community and tutors that arise out of this workshop are here for making the learning process run more smoothly, but are not obligated to baby-sit a person's progress. Because everyone will be working from the same textbook (Teach Yourself C++ in 21 days 5th Ed.), students may find it easier to get answers to the specific questions they might have. There is no minimum age requirement, and there is no previous programming experience required. Additionally, this workshop does not attempt to defend C++ as a language, nor does it attempt to demonstrate that C++ is either more or less useful then other programming languages for any particular purpose. People who intend to start a discussion about the differences between C++ and ANY other languages (except as are relevant to a particular discussion), are encouraged to do so elsewhere. This workshop is for educational, not philosophical discussions. Quizzes & Exercises Each week will have quizzes and exercises posted in the weekly threads. Please try and answer them by yourself. As well, please DO NOT post the answers to Quizzes and Exercises within this thread. Once it becomes acceptable to post the answers to quizzes and exercises, an additional thread will be created each week specifically for the purpose of posting quiz answers. If you try with reasonable effort but are unable to answer the questions or complete the exercises, feel free to post a clarification question here on the thread. Tutors, myself, or others will do the best we can to point you in the right direction for finding the answer.

Chapter 10 – Working with Advanced Functions

Introduction Heya all! Welcome back to the workshop...sorry I've kept you all waiting. There are many reasons for my absence, but the most relevant is that my computer melted when the CPU fan and Northbridge fan on my motherboard simultaneously stopped functioning. At any rate... This week is chapter 10. We will be focusing more on overloading member functions, operators, and constructors. We'll also take a look at initializer lists, the copy constructor, and type converters. The chapter for this week is roughly 35 pages. The primary purposes for the things learned in this chapter are convenience. By providing intelligent constructors, copy constructors, and the ability to overload operators you can make the interactions with your object more efficient and more intuitive. I will also be posting the information for Project 1 VERY soon, and it will be active for 4 weeks. People will need to draw not only from what we've learned, but from what we will learn over the next 4 weeks in order to complete the project successfully. Please remember to use OPINION and WARNING tags whenever applicable. As well, feel free to post your own insights, and review questions or exercises beginning Wednesday or Thursday. Outline of the Reading - Chapter 10
  1. Overloaded Member Functions
  2. Using Default Values
  3. Choosing Between Default Values and Overloaded Functions
  4. The Default Constructor
  5. Overloading Constructors
  6. Initializing Objects
  7. The Copy Constructor
  8. Operator Overloading
  9. Handling Data Type Conversion
  10. Conversion Operators

Good Luck!

[Edited by - jwalsh on May 30, 2007 1:01:40 PM]
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
Advertisement
I've read this chapter a few times and have probably found parts of it the most confusing so far and I have a number of questions. Rather than throw them all in at once, I'll "trickle" them so I don't get mixed up any further.

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?

I've read the section about overloading operators and I don't have a clue why this is important - but don't want to deal with that just now as there's something more fundamental that I need to clarify. In listings 10.7 and 10.8, I misinterpreted the "i" (in line 25 and 27) to be an integer but realise now that its an object of the class "Counter", which happens to be called "i". This is analagous to an object of the class "Cat" which is called "Frisky" or another one called "Boots". In each of 10.7 and 10.8, the object called "i" is incremented and it's value printed to the screen but I didn't think that an object could actually hold any data. If I move the analogy to Frisky and Boots, I've never seen anything like "cout << Frisky", but I have seen "cout << Frisky.itsAge" or "cout << Boots.itsWeight".

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.)?
Hi all, this is nice lesson I think. Just like CondorMan I would like to know whether Object of a class are used to access member function of a class only. Member function will use data member/variables used in it or access it through parameters used in the functions?

When Constructors are used should we also use destructors? It is little confusing. I also read that when we use new operator we should also use delete? Can someone explain more in detail about constructor/destructors usage together and new/delete operator?

Condor, all good questions...let me take a moment to answer them.

Quote: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?


No. This is not polymorphism. Polymorphism isnt when a function behaves differently based on the parameters, its when a function behaves differently based upon the object it belongs to. We'll cover it in more detail in chapter 14. Until we've covered the concept of inheritance, I cant even begin to explain it, as inheritance is fundamental to the concept of polymorphism.

Quote:I've read the section about overloading operators and I don't have a clue why this is important - but don't want to deal with that just now as there's something more fundamental that I need to clarify.


Actually, its kind of ironic that you say this. The problem that you're having with the i++ in the rest of the this paragraph is exactly why operator overloading is important. The example in 10.8 wont make any sense unless operator overloading makes sense.

Quote:In each of 10.7 and 10.8, the object called "i" is incremented and it's value printed to the screen but I didn't think that an object could actually hold any data.


In 10.7 the code calls i.increment(). This is just a method of the class, and as you can see on line 13, all the increment() method does is increment Counter::itsVal. On line 26 and 28 of 10.7 i.GetItsVal() is called to return the value stored in itsVal, a member variable of class Counter. So you can see now that the 'i' isnt being incremented, the value 'itsVal' is being incremented.

In 10.8 they duplicate the code for 10.7 exactly, with one small addition. On line 15 they add the operator++ method. This is operator overloading. By adding this method to the class, it tells the compiler that when someone uses the unary increment (++) operator on this class, to call that method. So on line 29 of 10.8 the Increment method is once again called. On line 31, instead of calling Increment the writer just used the '++' operator, which indirectly called the operator++ method. You'll notice that on line 14-15 both Increment and operator++ do the same thing.

In a nutshell, operator overloading just allows class writers to determine what happens to their object when used in conjunction with various operators. For example....think of a vector math class. What happens when you add two vectors together? What happens when you subtract two vectors? etc...rather than having to write:
Vector vec1(1.0, 1.0, 1.0);Vector vec2(1.0, 1.0, 1.0);Vector vec3 = vec1.Add( vec2 );

Operator overloading allows me to write:
Vector vec1(1.0, 1.0, 1.0);Vector vec2(1.0, 1.0, 1.0);Vector vec3 = vec1 + vec2;

You'll notice that now I'm able to use the '+' operator just as I would mathematically. And the '+' operator for this class knows that when you add two vectors together, you're actually adding the components of the vector together and creating a new vector. C++ doesnt know that by default.

Hope this helps. Let us know if you've got more questions or if this didnt fully answer your question.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
I think Jeromy's example with the vectors that can be added together is a lot better than the example in the book. I understand the concept of overloading operators, but when I saw the example in the book I thought: "Now why would someone do that?".
Operator overloading basically makes things more intuitive and easier to read. The functions that the overloaded operators perform can be accomplished just as easily with a function, but it makes it easier for the user to understand what is going on. The vector scenario is a perfect example of how operator overloading can make things easier to read.

Here's another example. Suppose you have created a class for dealing with very large numbers, called LargeNumber. Now, it is safe to assume that the user will want to add and subtract these numbers, so you can go about this one of two ways.

1) The first way, you use functions:
LargeNumber num1 = 2;
LargeNumber num2 = 10;
num1 = num1.Add( num2 );

2) The second way, you use operators:
LargeNumber num1 = 2;
LargeNumber num2 = 10;
num1 = num1 + num2;

See how more intuitive that is?
Mike Popoloski | Journal | SlimDX
[OPINION]
Quote:No. This is not polymorphism. Polymorphism isnt when a function behaves differently based on the parameters, its when a function behaves differently based upon the object it belongs to. We'll cover it in more detail in chapter 14. Until we've covered the concept of inheritance, I cant even begin to explain it, as inheritance is fundamental to the concept of polymorphism.


I consider function overloading a form of polymorphism. Polymorphism means 'taking many forms', it does not mean 'inheritence with virtual functions'. Polymorphism is itself polymorphic; it takes many forms, from what most people think of - inheritence - to interface restrictions imposed by templates. Function overloading is just another form of it. From the perspective of the calling code, all those overloaded functions are the same function, and it takes different forms depending on what kind of parameters you pass to it.
[/OPINION]

[WARNING]
When overloading operators, always prefer to make them behave like they would for built-in types. To make it simple; the + operator should add, and the - operator should subtract. Don't abuse them to make them do nonsensical things. Best case, you confuse yourself and others. Worst case, wrong code compiles and does nasty things.
[/WARNING]

Hey, what are the chances of getting the OPINION and WARNING things added to the forum as actual functioning tags?
Quote:Original post by Deyja
[OPINION]
Quote:No. This is not polymorphism. Polymorphism isnt when a function behaves differently based on the parameters, its when a function behaves differently based upon the object it belongs to. We'll cover it in more detail in chapter 14. Until we've covered the concept of inheritance, I cant even begin to explain it, as inheritance is fundamental to the concept of polymorphism.


I consider function overloading a form of polymorphism. Polymorphism means 'taking many forms', it does not mean 'inheritence with virtual functions'. Polymorphism is itself polymorphic; it takes many forms, from what most people think of - inheritence - to interface restrictions imposed by templates. Function overloading is just another form of it. From the perspective of the calling code, all those overloaded functions are the same function, and it takes different forms depending on what kind of parameters you pass to it.
[/OPINION]


[MORE OPINION!]
Though I would agree that technically operator overloading is a kind of polymorphism, I think it's a little pedantic to say so. In terms of the Object-Oriented paradigm polymorphism specifically refers to functions behaving differently based on the object it belongs to, as stated by jwalsh. In this case it is the objects themselves having many forms, those forms being defined by their member functions.
[/MORE OPINION!]

Thanks guys - it seems that my questions stimulated quite a response! I'll read the thread over a few times and then post any follow up questions for further clarification.

Just one point about polymorphism (and I speak as someone who's coming to programming languages from scratch, rather than having tried C++ previously and found it very difficult) - I've heard the term but don't know anything about it. I was under the impression that function overloading was polymorphism because of the following (page 119): "Function overloading is also called function polymorphism. Poly means many, and morph means form: A polymorphic function is many-formed".

I realise that there is discrepancy in that some of you do regard this as polymorphism whilst others don't.
Let me clarify....

The term polymorphism (lowercase p) refers to the ability of something to take on multiple forms. Function polymorphism then is the ability of a function to 'appear' to behave differently depending on the circumstances. In reality, there exists different functions that perform different actions, but the compiler selects the correct function to call depending upon the parameter list at compile-time. So in this regard, the function is polymorphic.

Polymorphism (capital p) is an Object Oriented term which describes an object's ability to behave as though it were a class different than that which is indicated. This is possible due to something called the Virtual Function Table which we will explore in more depth in the next 2 chapters (inheritance and polymorphism).

A quick example for the overzealous.
class BaseClass {public:    void MyControlFunction()    {        cout << "This is just a control function..." << endl;    }    virtual void MyFunction( void )    {        cout << "I belong to BaseClass" << endl;    }};class DerivedClass : public BaseClass {public:     virtual void MyFunction( void )    {        cout << "I belong to DerivedClass" << endl;    }}//.....// some time later//.....// Create a base class objectBaseClass* pBaseClass = new BaseClass;// Create a derived class objectDerivedClass* pDerivedClass = new DerivedClass;// Create a derived class object, but store it in a pointer to a base classBaseClass* pPolymorphicClass = new DerivedClass;//----------------------------------------// now lets call the output function on the pointer to the base class to// see what happens//----------------------------------------// This outputs "This is just a control function...", which makes sense// as this is a pointer to Base Class and MyControlFunction is a method of// BaseClasspBaseClass->MyControlFunction();// This outputs "I belong to BaseClass" as you might expectpBaseClass->MyFunction();//----------------------------------------// now lets call the output function on the pointer to the derived class to// see what happens//----------------------------------------// This outputs "This is just a control function..."  The reason being// is that pDerivedClass inherited the functionality from BaseClass.// So even though its not explicitly declared in DerivedClass, it's still // available to be calledpDerivedClass->MyControlFunction();// This outputs "I belong to DerivedClass"...This is because DerivedClass// overrides the function, thus "hiding" the implementation of BaseClass from// the outside worldpDerivedClass->MyFunction();//----------------------------------------// now lets call the output function on the base pointer to the derived class to// see what happens//----------------------------------------// This outputs "This is just a control function..."  The reason being// is that pPolymorphicClass is a pointer to a base class, and the function// is not virtual, so it calls the function which belongs to the type of the// pointer, in this case BaseClass*pPolymorphicClass->MyControlFunction();// This outputs "I belong to DerivedClass"...This is the tricky part.  Even// though this is a BaseClass pointer, the pointer actually points to a Derived// Class.  Since the method 'MyFunction' is virtual, the compiler instead// determines which method to call based on the object being pointed to, not// the type of the pointer.pPolymorphicClass->MyFunction();


So now hopefully you can see that by using inheritance, and a combination of base pointers to a derived class you can create unique solutions in which objects sometimes act like the base class (or any ancestor) and sometimes acts like the type being pointed to. This is "Polymorphism" (Capital P) in the Object Oriented paradigm.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints

This topic is closed to new replies.

Advertisement