Thread: Relating classes using composition

  1. #1
    Registered User
    Join Date
    Sep 2007
    Location
    Arizona
    Posts
    164

    Relating classes using composition

    Originally I created an inheritance for these two classes. I had everything working except one function in circleType, and last night laserlight helped debug that. Well, today I realize that this is a composition relationship not inheritance. So, I reworked all the code to reflect the new relation. And, again tonight I have one function that doesn't seem to be working right.

    The problem is in the circle function calls at the end of main. Everything works through the calc and print of the area and circum. But, the first cindyCircle.printPoint() function prints (0, 0) when it should print (3, 3). I thought this problem was in the cindyCircle.setPointRadius() function. But, the functions following it worked, so then I narrowed it down the the cindyCircle.printPoint() but I still can't get it to work. THe second cindyCircle.printPoint() works fine after I explicitly setX and setY.

    Can anyone see what I am not?
    Thanks!

    pointClass.h
    Code:
    #ifndef H_POINT
    #define H_POINT
    
    #include <iostream>
    using namespace std;
    
    class pointType
    {
    public:
    	pointType();
    	//default constructor
    	pointType(int xCoord, int yCoord);
    	//constructor
    	
    	void setPoint(int xCoord, int yCoord);
    	//stores the values of xCoord into x, and yCoord into y
    	void setX(int xCoord);
    	//stores the value of xCoord into x and y remains unchanged
    	void setY(int yCoord);
    	//x remains unchanged and stores the value of yCoord into y
    	void getPoint(int & xCoord, int & yCoord);
    	//returns the value of x into xCoord and y into yCoord
    	void getX(int & xCoord);
    	//returns just the value of x into xCoord
    	void getY(int & xCoord);
    	//returns just the value of y into yCoord
    	void printPoint() const;
    	//prints (x, y)
    	void printX()const;
    	//prints just x
    	void printY()const;
    	//prints just y
    
    private:
    	int x;
    	int y;
    };
    
    #endif
    pointClass.cpp
    Code:
    #include "pointClass.h"
    
    pointType::pointType()
    {
    	setPoint(0, 0);
    }
    
    pointType::pointType(int xCoord, int yCoord)
    {
    	setPoint(xCoord, yCoord);
    }
    
    void pointType::setPoint(int xCoord, int yCoord)
    {
    	x = xCoord;
    	y = yCoord;
    }
    
    void pointType::setX(int xCoord)
    {
    	x = xCoord;
    }
    
    void pointType::setY(int yCoord)
    {
    	y = yCoord;
    }
    
    void pointType::getPoint(int & xCoord, int & yCoord)
    {
    	xCoord = x;
    	yCoord = y;
    }
    
    void pointType::getX(int & xCoord)
    {
    	xCoord = x;
    }
    
    void pointType::getY(int & yCoord)
    {
    	yCoord = y;
    }
    
    void pointType::printPoint() const
    {
    	cout << "(" << x << ", " << y << ")" << endl;
    }
    
    void pointType::printX() const
    {
    	cout << "The value of x is: " << x << endl;
    }
    
    void pointType::printY() const
    {
    	cout << "The value of y is: " << y << endl;
    }
    circleClass.h
    Code:
    #ifndef H_CIRCLE
    #define H_CIRCLE
    
    #include <iostream>
    #include <string>
    #include <cmath>
    #include "pointClass.h"
    
    const double PI = 3.14159;
    
    class circleType: public pointType
    {
    public:
    	circleType();
    	circleType(int xCoord, int yCoord, int radius);
    
    	void setRadius(int radius);
    	void setPointRadius(int xCoord, int yCoord, int radius);
    	void getRadius(int & radius);
    	void getPointRadius(int & xCoord, int & yCoord, int & radius);
    
    	double calcArea();
    	double calcCircum();
    	void WhereAmI();
    
    	void printRadius() const;
    	void printArea();
    	void printCircum();
    	void printPointRadius() const;
    	
    
    private:
                    pointType x, y, point;
                    int r;
    };
    
    #endif
    circleClass.cpp
    Code:
    #include "pointClass.h"
    #include "circleClass.h"
    
    circleType::circleType()
    	:x(), y()
    {
    	r = 0;
    }
    
    circleType::circleType(int xCoord, int yCoord, int radius)
    		: x(x), y(y)
    {
    	r = radius;
    }
    
    void circleType::setRadius(int radius)
    {
    	r = radius;
    }
    
    void circleType::setPointRadius(int xCoord, int yCoord, int radius)
    {
    	x.setX(xCoord);
    	y.setY(yCoord);
    	point.setPoint(xCoord, yCoord);
    	r = radius;
    }
    
    void circleType::getRadius(int & radius)
    {
    	radius = r;
    }
    
    void circleType::getPointRadius(int & xCoord, int & yCoord, int & radius)
    {
    	point.getX(xCoord);
    	point.getY(yCoord);
    	radius = r;
    }
    
    double circleType::calcArea()
    {
    	return (PI * pow(r, 2));
    }
    
    double circleType::calcCircum()
    {
    	return (2 * PI * r);
    }
    
    void circleType::printRadius() const
    {
    	cout << "The current value of radius is: " << r << endl;
    }
    
    void circleType::printArea()
    {
    	cout << "The area of a circle with a radius of " 
    		 << r << " is " << calcArea() << endl;
    }
    
    void circleType::printCircum()
    {
    	cout << "The circumference of a circle with a radius of "
    		 << r << " is " << calcCircum() << endl;
    }
    
    void circleType::printPointRadius() const
    {
    	point.printPoint();
    	x.printX();
    	y.printY();
    	cout << " and the radius of the circle is " << r << "." << endl;
    }
    
    void circleType::WhereAmI()
    {
    	int xCoord,
    		yCoord;
    	point.getPoint(xCoord, yCoord);
    	x.getX(xCoord);
    	y.getY(yCoord);
    	if (xCoord > 0 && yCoord > 0)
    		cout<< "My Center is in the first quadrant of the cartesian plane." << endl;
    	else if (xCoord > 0 && yCoord < 0)
    		cout << "My Center is in the second quadrant of the cartesian plane." << endl;
    	else if (xCoord < 0 && yCoord < 0)
    		cout << "My Center is in the third quadrant of the cartesian plane." << endl;
    	else 
    		cout << "My Center is in the fourth quadrant of the cartesian plane." << endl;
    }
    main.cpp
    Code:
    #include "pointClass.h"
    #include "circleClass.h"
    
    //to test the pointClass prior to building the circleClass
    int main()
    {
    	int mainX = 0,
    		mainY = 0,
    		returnValue = 0;
    
    	//operation calls to check the point class
    	pointType cindyPoint;
    	
    	cout << "The x and y values of cindyPoint are: ";
    	cindyPoint.printPoint();
    	cindyPoint.setX(19);
    	cindyPoint.setY(57);
    	cout << "The new x and y values of cindyPoint are: ";
    	cindyPoint.printPoint();
    	cout << "Before the get functions, mainX = " << mainX << ", mainY = " << mainY
    		<< ", \n\tand returnValue (mainX + mainY) = " << returnValue << "." << endl;
    	cindyPoint.getX(mainX);
    	cindyPoint.getY(mainY);
    	returnValue = mainX + mainY;
    	cout << "After the get functions, mainX = " << mainX << ", mainY = " << mainY
    		<< ", \n\tand returnValue (mainX + mainY) = " << returnValue << "." << endl;
    	
    	pointType badPoint;
    	
    	cout << "The x and y values of badPoint are: ";
    	badPoint.printPoint();
    	badPoint.setX(32);
    	badPoint.setY(23);
    	badPoint.printX();
    	badPoint.printY();
    	cout << "The x and y values of badPoint are now: ";
    	badPoint.printPoint();
    	badPoint.setPoint(-62, -78);
    	cout << "The x and y values of badPoint have been reset to: ";
    	badPoint.printPoint();
    
    
    	//operation calls to check the circle class
    	circleType cindyCircle;
        
    	cout << "\ncindyCircle has default x and y values of: ";
    	cindyCircle.printPointRadius();
    	cindyCircle.setPointRadius(3, 3, 3);
    	cout << "cindyCircle has reset values to: ";
    	cindyCircle.printPointRadius();
    	cindyCircle.calcArea();
    	cindyCircle.printArea();
    	cindyCircle.calcCircum();
    	cindyCircle.printCircum();
    	cout << "The x and y values of cindyPoint now are: ";
    	cindyCircle.printPoint();
    	cindyCircle.WhereAmI();
    	cindyCircle.setX(-3);
    	cindyCircle.setY(-3);
    	cout << "The x and y values of cindyPoint now are: ";
    	cindyCircle.printPoint();
    	cindyCircle.WhereAmI();
    }
    Last edited by clegs; 11-04-2007 at 11:38 PM.

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Code:
    circleType::circleType(int xCoord, int yCoord, int radius)
    		: x(x), y(y)
    This code isn't right. You're using x and y to initialize themselves and ignoring xCoord and yCoord.

    Your circleType class has a pointType x and pointType y. Shouldn't you just have a single pointType for x and y? In fact, shouldyou just have pointType center or something that holds the single point that is the center of the circle? Your constructor can still take an xCoord and yCoord, you would then just pass both to the constructor of your center variable.

    BTW, I definitely agree that you want composition, not inheritance here.

  3. #3
    Registered User
    Join Date
    Sep 2007
    Location
    Arizona
    Posts
    164
    If I have just a single pointType for both x & y, then if I want to initialize them separately is there a problem?

  4. #4
    Registered User
    Join Date
    Sep 2007
    Location
    Arizona
    Posts
    164
    I modified my circleType class and added a few more functions which seems to have corrected the problem I just don't know if what I did is "correct." I will repost the circleType .h and .cpp for review by you all.

    Feel free to hack away. I am just feeling myself through all this. My instructor is absent in all of this and when he does respond I wonder... This is his last:
    "A large part of programming, as you are finding out, is “rolling up your shirt sleeve” and trying a solution or “if you don’t succeed…”. Also you will find that there is more than one way."
    Well Duh!

    NEW circleType.h
    Code:
    #ifndef H_CIRCLE
    #define H_CIRCLE
    
    #include <iostream>
    #include <string>
    #include <cmath>
    #include "pointClass.h"
    
    const double PI = 3.14159;
    
    class circleType: public pointType
    {
    public:
    	circleType();
    	circleType(int xCoord, int yCoord, int radius);
    
    	void setRadius(int radius);
    	void setX(int xCoord);
    	void setY(int yCoord);
    	void setPoint(int xCoord, int yCoord);
    	void setPointRadius(int xCoord, int yCoord, int radius);
    	void getRadius(int & radius);
    	void getPointRadius(int & xCoord, int & yCoord, int & radius);
    
    	double calcArea();
    	double calcCircum();
    	void WhereAmI();
    
    	void printRadius() const;
    	void printPoint() const;
    	void printArea();
    	void printCircum();
    	void printPointRadius() const;
    	
    
    private:
    	pointType x, y, point;
    	int r;
    };
    
    #endif
    NEW circleType.cpp
    Code:
    #include "pointClass.h"
    #include "circleClass.h"
    
    circleType::circleType()
    	:x(), y()
    {
    	r = 0;
    }
    
    circleType::circleType(int xCoord, int yCoord, int radius)
    		: x(x), y(y)
    {
    	r = radius;
    }
    
    void circleType::setPoint(int xCoord, int yCoord)
    {
    	point.setPoint(xCoord, yCoord);
    }
    
    void circleType::setX(int xCoord)
    {
    	point.setX(xCoord);
    }
    
    void circleType::setY(int yCoord)
    {
    	point.setY(yCoord);
    }
    
    void circleType::setRadius(int radius)
    {
    	r = radius;
    }
    
    void circleType::setPointRadius(int xCoord, int yCoord, int radius)
    {
    	x.setX(xCoord);
    	y.setY(yCoord);
    	point.setPoint(xCoord, yCoord);
    	r = radius;
    }
    
    void circleType::getRadius(int & radius)
    {
    	radius = r;
    }
    
    void circleType::getPointRadius(int & xCoord, int & yCoord, int & radius)
    {
    	point.getX(xCoord);
    	point.getY(yCoord);
    	radius = r;
    }
    
    double circleType::calcArea()
    {
    	return (PI * pow(r, 2));
    }
    
    double circleType::calcCircum()
    {
    	return (2 * PI * r);
    }
    
    void circleType::printRadius() const
    {
    	cout << "The current value of radius is: " << r << endl;
    }
    
    void circleType::printArea()
    {
    	cout << "The area of a circle with a radius of " 
    		 << r << " is " << calcArea() << endl;
    }
    
    void circleType::printCircum()
    {
    	cout << "The circumference of a circle with a radius of "
    		 << r << " is " << calcCircum() << endl;
    }
    
    void circleType::printPoint() const
    {
    	point.printPoint();
    }
    
    void circleType::printPointRadius() const
    {
    	point.printPoint();
    	cout << " and the radius of the circle is " << r << "." << endl;
    }
    
    void circleType::WhereAmI()
    {
    	int xCoord,
    		yCoord;
    	point.getPoint(xCoord, yCoord);
    	x.getX(xCoord);
    	y.getY(yCoord);
    	if (xCoord > 0 && yCoord > 0)
    		cout<< "My Center is in the first quadrant of the cartesian plane." << endl;
    	else if (xCoord > 0 && yCoord < 0)
    		cout << "My Center is in the second quadrant of the cartesian plane." << endl;
    	else if (xCoord < 0 && yCoord < 0)
    		cout << "My Center is in the third quadrant of the cartesian plane." << endl;
    	else 
    		cout << "My Center is in the fourth quadrant of the cartesian plane." << endl;
    }

  5. #5
    Registered User
    Join Date
    Sep 2007
    Location
    Arizona
    Posts
    164
    So, if I have point.getPoint() I can also have point.getX() and point.getY() ?
    And would that would eliminate some of the redundancy I feel I have in my definitions.? To use point.getX and Y or point.setX and Y etc...

  6. #6
    Registered User
    Join Date
    Sep 2007
    Location
    Arizona
    Posts
    164
    I think I figured it out. I took your advice Daved and changed :x(x), y(y). It wasn't working when I included defined values in the initialization of my circleType.

    Code:
    circleType::circleType(int xCoord, int yCoord, int radius)
    		: x(x), y(y)
    now looks like:
    Code:
    circleType::circleType(int xCoord, int yCoord, int radius)
    	:point(xCoord, yCoord)
    Now the define value constructor uses the correct values instead of initializing the point to (0, 0) and the radius to the defined value.

    Thanks, I think I may have it worked out, but I will check back to see if anyone else has found more errors that I haven't uncovered yet.
    Thanks!

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    It just makes more sense that way, right? You have to understand what the things represent. Your circle's data consists of a center point and a radius, right? So you only need one member variable point and one member variable for the radius.

    You also have to think of pointType as a type. Forget the x and y parts of it, if you want a point, use a pointType.

  8. #8
    Registered User
    Join Date
    Sep 2007
    Location
    Arizona
    Posts
    164
    I am trying to understand!

    That part, I thought, was working until you pointed out the problem. So I added values to the declaration and it didn't work! So...I fixed it the way you suggested.

    I write everything out and think things through, or so I think, before ever typing a word. Then when things don't work, I start changing what I think the problem is, and sometimes, I get so deep, that I have to step away and backtrack a ways. I have started coping the code I am going to change into word before I change it. That way, if what I think will work doesn't, I can go back to what I had and rethink yet again.

    It hasn't been too difficult so far, once I understand what the book is "trying" to explain. Sometimes, that isn't done too well.

    Thanks for your help Daved.

    My next assignment is to create a cylinder class using all of the above. I will definately use composition from the beginning. There is nothing worse than doing an assignment twice. I sure did learn a bit more than I expected about both inheritance and composition.
    Last edited by clegs; 11-05-2007 at 01:05 AM.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I'm not saying you are a bad programmer for not understanding, I'm saying that when you understand what different things mean before you code it makes the coding easier. Everything you describe about making changes until you get so deep that it is all confusing is normal for pretty much all programmers. Just keep working and do your best to "step back" for every decision you make.

  10. #10
    Registered User
    Join Date
    Sep 2007
    Location
    Arizona
    Posts
    164
    Thanks, but I am not a programmer, I am a student of programming at this point.
    I aspire to be a programmer, but time will tell if I have what it takes, and what language suits me. I may just have to stay in finance.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Well, surely even in Finance programming, you will sooner or later have to work on something you are not familiar with. What if your financial software requires that you draw a bunch of symbols in a graph - wouldn't a basic understanding of classes and inhearitance be really helpful?

    It is always difficult when you start out with a new project, or a new area that you are not familiar with. It's part of the challenge in programming - and it can be hard at times, but the feeling when you get it working is great.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    class circleType: public pointType
    {
    public:
    	circleType();
    	circleType(int xCoord, int yCoord, int radius);
    
    	void setRadius(int radius);
    	void setX(int xCoord);
    	void setY(int yCoord);
    	void setPoint(int xCoord, int yCoord);
    	void setPointRadius(int xCoord, int yCoord, int radius);
    	void getRadius(int & radius);
    	void getPointRadius(int & xCoord, int & yCoord, int & radius);
    
    	double calcArea();
    	double calcCircum();
    	void WhereAmI();
    
    	void printRadius() const;
    	void printPoint() const;
    	void printArea();
    	void printCircum();
    	void printPointRadius() const;
    	
    
    private:
    	pointType x, y, point;
    	int r;
    };
    Are you still deriving from pointType? What about the const-ness of those other functions?
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  13. #13
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    All the versions of code posted so far use both composition AND inheritance.
    In fact in that code, there are four instances of pointType, in every circleType instance.
    Including the 'r' that's 4x2+1 = 9 intetgers, or 36 bytes for every circle.

    Don't derive from pointType, and only declare one pointType member.
    This will bring the class size down do 1x2+1 = 3 integers, or 12 bytes for every circle.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can you Initialize all classes once with New?
    By peacerosetx in forum C++ Programming
    Replies: 12
    Last Post: 07-02-2008, 10:47 AM
  2. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 09:04 AM
  3. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  4. Exporting VC++ classes for use with VB
    By Helix in forum Windows Programming
    Replies: 2
    Last Post: 12-29-2003, 05:38 PM
  5. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM