Classes

Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
Reply

Join Date: Sep 2004
Posts: 421
Reputation: JoBe is on a distinguished road 
Solved Threads: 4
JoBe's Avatar
JoBe JoBe is offline Offline
Posting Pro in Training

Re: Classes

 
0
  #11
Apr 6th, 2005
Thanks for the answers Narue, Ive been debugging your example, but several parts are to complicated for me to understand.

I thinks this is because there are several subjects Ive either just scratched the surface from (pointers, structures) and others I never read anything about yet.
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,867
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 755
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Senior Bitch

Re: Classes

 
0
  #12
Apr 6th, 2005
The syntax may be a little confusing as I was going for relatively concise code and didn't include error checks. Dereferencing a pointer returned by a function that can return a null pointer to get an object for immediate assignment isn't exactly the smartest thing in the world.
New members chased away this month: 5
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 421
Reputation: JoBe is on a distinguished road 
Solved Threads: 4
JoBe's Avatar
JoBe JoBe is offline Offline
Posting Pro in Training

Re: Classes

 
0
  #13
Apr 6th, 2005
Originally Posted by Narue
Dereferencing a pointer returned by a function that can return a null pointer to get an object for immediate assignment isn't exactly the smartest thing in the world.
You know, saying what you said above or saying it in Chinees to me, would have the same result :cheesy:

I'm asking myself, what the h*ll did she just say
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,867
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 755
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Senior Bitch

Re: Classes

 
0
  #14
Apr 6th, 2005
>saying what you said above or saying it in Chinees to me, would have the same result
:cheesy: It basically means that this:
  1. T obj = *function();
Is generally an unsafe practice. It should be:
  1. T *p = function();
  2. T obj;
  3. if ( p != 0 )
  4. obj = *p;
New members chased away this month: 5
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 421
Reputation: JoBe is on a distinguished road 
Solved Threads: 4
JoBe's Avatar
JoBe JoBe is offline Offline
Posting Pro in Training

Re: Classes

 
0
  #15
Apr 6th, 2005
> T *p = function();
This means, that your declaring an object as a pointer with a function as variable?

> T obj;
Declaration of an object in a class.

>if ( p != 0 )
obj = *p;

If the value of p is not equal to zero, ... then Ive lost you, you put the pointer into the object???

I'm just trying to break it apart so it's abit clearer to me :!:
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,867
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 755
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Senior Bitch

Re: Classes

 
0
  #16
Apr 6th, 2005
>This means, that your declaring an object as a pointer with a function as variable?
Defining a pointer to T and initializing it with the return value of a function.

>Declaration of an object in a class.
T stands for a generic type, so it could be a class object or an object of built in type.

>If the value of p is not equal to zero
Also read as "if p is not a null pointer".

>you put the pointer into the object???
Assign the data that the pointer points to, to the object.
New members chased away this month: 5
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 421
Reputation: JoBe is on a distinguished road 
Solved Threads: 4
JoBe's Avatar
JoBe JoBe is offline Offline
Posting Pro in Training

Re: Classes

 
0
  #17
Apr 14th, 2005
Hi guys,

Next exercise:

Write a class Fractions to work with Fractions, like this for example:

Fractions a(3, 8) , b(4, 5), c = a * b;

Wich should result into de fractions a, b en c: 3/8, 4/5 and 3/10 (= 3/8 * 4/5).

Clues: Start with the operator* and / and add the more difficult operators + and - afterwards. Use the Greatest Common Divider function wich was used in exercise 4.4 to simplify fractions. When adding and subtracting with fractions you have to make sure that the denominators are made equal for wich you can use GCD function aswell. The Smallest Common Multiplicator for the denominator x and y can be calculated with: SCM(x, y) = xy/ GCD(x, y)

What Ive got so far is the multiplier operator* wich is this:

  1. class Fractions
  2. {
  3. public:
  4. Fractions ( short a = 0, short b = 0) : numerator (a), denominator (b){}
  5.  
  6. Fractions operator* (Fractions d)
  7. {
  8. Fractions result;
  9.  
  10. result.numerator = numerator * d.numerator;
  11. result.denominator = denominator * d.denominator;
  12.  
  13. while (result.denominator % 2 == 0 && result.numerator % 2 == 0)
  14. {
  15. result.numerator /= 2;
  16. result.denominator /= 2;
  17. }
  18.  
  19. return result;
  20. }
  21.  
  22. void print()
  23. {
  24. cout<< numerator << "/" << denominator <<endl;
  25. }
  26.  
  27. private:
  28. short numerator, denominator;
  29. };
  30.  
  31. int main()
  32. {
  33. Fractions fract1 (3, 8), fract2 (4, 5), c;
  34.  
  35. fract1.print();
  36. fract2.print();
  37.  
  38. c = fract1 * fract2;
  39.  
  40. c.print();
  41.  
  42. return 0;
  43. }

This works out the way it should, meaning that my results are 3/8, 4/5 and 3/10.

But I was wondering wether this part could be written shorter or better:
  1. Fractions operator* (Fractions d)
  2. {
  3. Fractions result;
  4.  
  5. result.numerator = numerator * d.numerator;
  6. result.denominator = denominator * d.denominator;
  7.  
  8. while (result.denominator % 2 == 0 && result.numerator % 2 == 0)
  9. {
  10. result.numerator /= 2;
  11. result.denominator /= 2;
  12. }
  13.  
  14. return result;
  15. }

I was also wondering wether it wouldn't be better to write a separate class function for this piece of code, so that I maybe could use it for the other operators aswell if this works out to be necessary?
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,867
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 755
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Senior Bitch

Re: Classes

 
0
  #18
Apr 14th, 2005
For reducing the fraction, a separate function that finds the greatest common divisor would be a good idea. Then you should define an explicit reduce member function since it's an operation you'll use a lot. It would also be a good idea for operator* to be a non-member function since it doesn't have to be called on behalf of either operand. Then you could change your operator* to:
  1. void Fraction::reduce()
  2. {
  3. short div = gcd ( numerator, denominator );
  4.  
  5. numerator /= div;
  6. denominator /= div;
  7. }
  8.  
  9. Fraction operator* ( const Fraction& a, const Fraction& b )
  10. {
  11. Fraction result;
  12.  
  13. result.numerator = a.numerator * b.numerator;
  14. result.denominator = a.denominator * b.denominator;
  15. result.reduce();
  16.  
  17. return result;
  18. }
New members chased away this month: 5
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 421
Reputation: JoBe is on a distinguished road 
Solved Threads: 4
JoBe's Avatar
JoBe JoBe is offline Offline
Posting Pro in Training

Re: Classes

 
0
  #19
Apr 14th, 2005
Hi Narue,

Thanks for the explanation, few questions tough before I go further with this exercise.

> It would also be a good idea for operator* to be a non-member function...
1) Do you mean that it would be best to write this function outside the class? Don't understand what you're trying to explain to me :-|

  1. Fraction operator* ( const Fraction& a, const Fraction& b )
2) why do you make Fraction constant?
3) why do you make two arguments and make them references? I tought that the first (numerator (3), denominator(8)) goes to operator* and the second (numerator(4), denominator(5)) goes to the argument
  1. Fraction d
as in my program, so, I tought there wasn't a second argument necessary?

4) So, the only thing I have to write the code for is the
  1. gcd ( numerator, denominator );
function correct?

5) Also, when I change my code like you wrote
  1. Fraction operator* (const Fraction& a, const Fraction& b)
I get an error saying that Ive got to many parameters, I'm sure it's got to do with this piece of code in main
  1. c = fract1 * fract2;
It's mentioned in the exercise to write it this way in main!
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,867
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 755
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Senior Bitch

Re: Classes

 
0
  #20
Apr 14th, 2005
>Do you mean that it would be best to write this function outside the class?
Yes. Instead of this:
  1. class Fraction {
  2. public:
  3. Fraction operator* ( const Fraction& rhs );
  4. ...
  5. };
  6.  
  7. Fraction Fraction::operator* ( const Fraction& rhs )
  8. {
  9. ...
  10. }
You would do this:
  1. class Fraction {
  2. public:
  3. friend Fraction operator* ( const Fraction& lhs, const Fraction& rhs );
  4. ...
  5. };
  6.  
  7. Fraction operator* ( const Fraction& lhs, const Fraction& rhs )
  8. {
  9. ...
  10. }
I forgot to mention making it a friend in my other post, sorry.

>2) why do you make Fraction constant?
Because you don't change any of the data members. By making the parameters const, you'll be warned if any changes made to the function try to make modifications. More importantly, you can pass constant objects to the function:
  1. const Fraction a ( 2, 3 );
  2. const Fraction b ( 5, 10 );
  3. Fraction c = a * b;
>3) why do you make two arguments and make them references?
operator* can be either a member function with one argument, or a non-member function with two arguments. When it's a member function, the object that you call the function on acts as the left side operand and the argument acts as the right side operand. When it's a non-member function, the first argument is the left side operand and the second argument is the right side operand.

The reason I used a non-member function is because you should strive to keep your class interface as sparse as possible. Any operations that can be made non-member functions or non-member friends should be. If we were talking about operator*= then it would be a member function, but operator* doesn't need to be.

It's generally best to pass class objects by reference to avoid the overhead of calling the copy constructor. If the object isn't going to be changed, pass by const reference.

>So, the only thing I have to write the code for is the
Correct.

>I get an error saying that Ive got to many parameters
You're still defining it as a member function. See my second example using a friend and match your code to that.

>It's mentioned in the exercise to write it this way in main!
It's always written that way unless you want to do it without the abstraction. Your error is trying to mix a non-member operator overload with a member operator overload. You have to do one or the other.
New members chased away this month: 5
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:




Views: 5569 | Replies: 44
Thread Tools Search this Thread



Tag cloud for C++
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC