OOPs, I did it again.... lol....

This is a discussion on OOPs, I did it again.... lol.... within the C++ Programming forums, part of the General Programming Boards category; I thought it was funny..... Anyways.... Object Oriented Programmers = Engineers? Objects - bits of code that should be able ...

  1. #1
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964

    OOPs, I did it again.... lol....

    I thought it was funny..... Anyways....

    Object Oriented Programmers = Engineers?

    Objects - bits of code that should be able to be re implemented, reused, and manipulated at will.... = nuts and bolts? wood? electrical wires?

    Object oriented programmers - software engineers


    In programming class, what did I learn about? I learned about classes, arrays, enums, all kinda of data types, structures, functions, loops.....

    But, what didn't we learn (well they tried, but didn't put enough emphasis on?)

    We didn't learn how to create object oriented programs. Why is it so hard for me to think in an object oriented manner?

    Right now I have a program, my first big one, running on 2700 lines of code, which has about 10 classes in it... that can't be good? It is mainly procedural...

    I understand inheritence, that part is easy, but like, how do classes use each other? How do they work together? theyre seperate objects....

    Anyone have any real helpful insight into OOP?

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Object oriented programming is about treating things as objects. Consider an object such as a box. YOu can look at it and get all kinds of information from it. It's dimensions, it's color, it's material, it's contents. You wouldn't go and get this information from something unrelated.
    In an OOP program we can cobine all of this information into a class and once we create an instance of that class we can access all the information about that class by using member variables and meathods of that class.
    for example we could call a meathod of a box class to get it's color and compare that color to another box object.
    Code:
    if (Box1.GetColor()==Box2.GetColor())
    A class can be used as a "black box". You don't need to know how meathods work only what they do an what they return or what private meathods/variables of the class do, you just need to know the class's interface and you can interact with that object.
    Don't other use OOP, use it in situations where creating a class makes it easier to understand a problem or more convieniant. You don't have to make a class for everything.

  3. #3
    Super Moderator Harbinger's Avatar
    Join Date
    Nov 2004
    Posts
    74
    Perhaps you should learn some object oriented design as well.

    Simply throwing a few unplanned classes into a program doesn't produce a well designed program which uses OOP to its best effect.

    > It is mainly procedural...
    Yep, that's it exactly - a complete lack of a design.

    > I understand inheritence,
    In the same way that understanding putting fuel into a car will make it go, but it doesn't make you a driver.

  4. #4
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    Here is what I have so far for my game, in terms of object oriented programming

    I have a class GameWorld, its responsiblities are only to handle coordinates of the game world and to communicate with the class Mobiles, mobiles sends coordinates to GameWorld...

    There are multiple instances of Mobile, here is where the inheritence comes in, Mobiles is a shell, I'm either going it into 2 sections (NPC and Player mobiles) and then add more instances of Mobile::NPC (for different units and such) or, just create a mess of Mobiles::StarFighter Mobiles:: Player Mobiles::StarDefender....


    What do you think?

  5. #5
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    Here it is, Please judge and make suggestions

    class GameWorld

    Responsibilities: Handle coordinates and other global world information

    Communicates with: Mobiles, Statics

    class Mobiles

    Responsibilities: Tells GameWorld where each inherited mobile is, holds mobile info. Recieves information from Statics (collision detection variables, etc)

    Communicates with: GameWorld, Statics

    class Statics

    Responsibilities: Holds info for static objects (Planets, stars, asteroids), passes info to GameWorld, Sends collision detection information variable to Mobiles

    Communicates with: GameWorld, Mobiles

    Code:
    class GameWorld
    {
    public:
    	int SizeX;
    	int SizeY;
    	int SizeZ;
    	void GetMobileLocation(void)
    	{
    	}
    	void GetStaticLocation(void)
    	{
    	}
    };
    
    class Mobiles
    {
    public:
    	int MLocationX;
    	int MLocationY;
    	int MLocationZ;
    	void GetCollisionInfo(void)
    	{
    	}
    };
    
    class Statics
    {
    public:
    	int SLocationX;
    	int SLocationY;
    	int SLocationz;
    	void InitCollisionInfo(void)
    	{
    	}
    };
    But aren't Mobiles and Statics essentially just things inside of the GameWorld Class, so actually I guess it could go like this: GameWorld->Objects->Statics and Mobiles... Right? Then each static and mobile could pass collision detection info to objects and have it handle all that...

    But technically, the only thing that needs to know collision information is mobiles... GameWorld doesn't necessarily need to know, right? So confused...
    Last edited by Shamino; 11-16-2005 at 02:17 AM.

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    I understand inheritence, that part is easy, but like, how do classes use each other? How do they work together? theyre seperate objects....
    Here are some examples:

    (Note: don't let vectors or other STL containers and their notation scare you. A vector is similar to an array except it doesn't have a fixed size, so you can add as many elements to it as you want. Typically, you add another element using push_back(), which adds the element to the end of the vector. In addition, the notation tells you what's in the vector, e.g.:

    vector<int> myInts;

    The vector, which remember is like an array, can contain integers. Here's another one:

    vector<Card> myCards;

    The vector can contain Card objects. Finally,

    vector<Card*> deck;

    The vector can store pointers to Card objects.)

    A Deck of Card's that can be shuffled, displayed, and dealt.
    Code:
    #include <iostream>
    #include <ctime> //time()
    #include <vector> 
    #include <algorithm> //random_shuffle()
    using namespace std;
    
    class Card
    {
    public:
    	Card(int rank_, int suit_)
    	{
    		rank = rank_;
    		suit = suit_;
    	}
    	
    	Card()
    	{
    		rank = suit = 0;
    	}
    
    	//To be able to cout<< Card(s):
    	friend ostream& operator<<(ostream& out, const Card* aCard);
    	friend ostream& operator<<(ostream& out, const vector<Card*>& aHand);
    
    private:
    	int rank;
    	int suit;
    };	
    
    //To cout<< one Card:
    ostream& operator<<(ostream& out, const Card* aCard)
    {
    	switch (aCard->rank)
    	{
    	case 2:
    	case 3:
    	case 4:
    	case 5:
    	case 6:
    	case 7:
    	case 8:
    	case 9:
    	case 10:
    		cout<<aCard->rank;
    		break;
    	case 1:
    		cout<<"Ace";
    		break;
    	case 11:
    		cout<<"Jack";
    		break;
    	case 12:
    		cout<<"Queen";
    		break;
    	case 13:
    		cout<<"King";
    		break;
    	default:
    		cout<<"error";
    	}
    	
    	switch(aCard->suit)
    	{
    	case 1:
    		cout<<" of Clubs";
    		break;
    	case 2:
    		cout<<" of Diamonds";
    		break;
    	case 3:
    		cout<<" of Hearts";
    		break;
    	case 4:
    		cout<<" of Spades";
    		break;
    	default:
    		cout<<"error";
    	}
    
    	return out;
    		
    }
    
    //A function that enables you to cout<< a vector of 
    //Card's(either a hand or a deck).  It's the same function as for
    //displaying a single card, but with a for loop to go through the
    //whole vector:
    ostream& operator<<(ostream& out, const vector<Card*>& aHand)
    {
    	for(int i = 0; i < aHand.size(); i++)
    	{
    		switch (aHand[i]->rank)
    		{
    		case 2:
    		case 3:
    		case 4:
    		case 5:
    		case 6:
    		case 7:
    		case 8:
    		case 9:
    		case 10:
    			cout<<aHand[i]->rank;
    			break;
    		case 1:
    			cout<<"Ace";
    			break;
    		case 11:
    			cout<<"Jack";
    			break;
    		case 12:
    			cout<<"Queen";
    			break;
    		case 13:
    			cout<<"King";
    			break;
    		default:
    			cout<<"error";
    		}
    		
    		switch(aHand[i]->suit)
    		{
    		case 1:
    			cout<<" of Clubs";
    			break;
    		case 2:
    			cout<<" of Diamonds";
    			break;
    		case 3:
    			cout<<" of Hearts";
    			break;
    		case 4:
    			cout<<" of Spades";
    			break;
    		default:
    			cout<<"error";
    		}
    		
    		cout<<endl;
    		
    		//Prevents scrolling off the screen:
    		if( (i != 0) && (i%20 == 0))
    		{
    			cout<<"Continue? <Hit Return>";
    			cin.get();
    			cout<<endl;
    		}
    	}
    
    	return out;
    }
    
    
    class Deck
    {
    public:
    	Deck()
    	{
    		for(int i=1; i <= 13; i++)
    		{
    			for(int j=1; j <= 4; j++)
    			{
    				//Add a card to the end of the deck member variable:
    				deck.push_back(new Card(i, j)); 
    			}
    		}
    
    
    		delt = 0;
    	}
    	
    	~Deck()
    	{
    		//Delete the memory allocated with new:
    		for(vector<Card*>::iterator i = deck.begin(); i != deck.end(); i++)
    		{
    			delete *i;
    		}
    	}
    	
    	void showDeck()
    	{
    		cout<<deck<<endl;
    	}
    
    	void shuffle()
    	{
    		//Seed random number generator with current time:
    		srand(time(0));
    		
    		//Shuffle deck:
    		random_shuffle(deck.begin(), deck.end());
    		
    		//After shuffling, set the number of cards dealt back to 0:
    		delt = 0;
    	}
    	
    	void deal(const int numCards, vector<Card*>& theHand)
    	{
    		for(int i=0; i<numCards; i++)
    		{
    			if(delt < 52)
    			{
    				//No cards are actually delt from the deck: pointers to Card's
    				//in the deck are put in the Hand instead, and the Cards all stay in the 
    				//deck.  The member variable 'delt' is advanced from the top of the
    				//deck down into the deck as the cards are delt, and it marks where 
    				//the next card is.
    				theHand.push_back(deck[delt]);
    				++delt;
    			}
    			else
    				theHand[i] = 0;
    		}
    	}
    	
    	//A function to cout<< the 'deck' member variable
    	//(uses same friend function as Card):
    	friend ostream& operator<<(ostream& out, const vector<Card*>& deck);
    	
    	
    private:
            //A vector of Card pointers is similar to an array of Card pointers:
    	vector<Card*> deck; 
    	
    	int delt;
    };
    
    
    int main() 
    {
    	
    	Deck myDeck;
    	myDeck.showDeck();
    	myDeck.shuffle();
    
    	vector<Card*> player1;
    	vector<Card*> player2;
    	myDeck.deal(5,player1);
    	myDeck.deal(5,player2);
    
    	cout<<player1<<endl<<endl
    		<<player2<<endl;
    
    
    	return 0;
    }
    Ducks and Inheritance:
    Code:
    #include<iostream>
    using namespace std;
    
    class Duck
    {
    public:
    	virtual void species() = 0;
    };
    
    ////////////////////////////
    class Sound
    {
    public:
    	virtual void speak() = 0;
    };
    
    class Quack: public Sound
    {
    private:
    	void speak()
    	{
    		cout<<"Quack, quack."<<endl;
    	}
    };
    
    class Squeak: public Sound
    {
    private:
    	void speak()
    	{
    		cout<<"Squeak, squeak."<<endl;
    	}
    };
    //////////////////////////////
    
    
    class Mallard : public Duck
    {
    public:
    	Mallard()
    	{
    		Q = new Quack;
    	}
    
    	~Mallard()
    	{
    		delete Q;
    	}
    
    	void species()
    	{
    		cout<<"Mallard"<<endl;
    	}
    
    	Quack* getSound()
    	{
    		return Q;
    	}
    
    private:
    	Quack* Q;
    };
    
    
    class RubberDuck : public Duck
    {
    public:
    	RubberDuck()
    	{
    		S = new Squeak;
    	}
    	~RubberDuck()
    	{
    		delete S;
    	}
    
    	void species()
    	{
    		cout<<"Rubber"<<endl;
    	}
    
    	Squeak* getSound()
    	{
    		return S;
    	}
    
    private:
    	Squeak* S;
    };
    
    //Because the following function has parameters that are base
    //class pointers it can handle any Duck that makes any Sound.
    void operateDuck(Duck* const pDuck, Sound* const pSound)
    {
    	pDuck->species();
    	pSound->speak();
    }
    	
    int main()
    {
    	Mallard myDuck;
    	RubberDuck yourDuck;
    
    	operateDuck(&myDuck, myDuck.getSound());
    	cout<<endl;
    	operateDuck(&yourDuck, yourDuck.getSound());
    	
    	return 0;
    }
    That is what I vaguely remember of the first design problem in the book "Head First Design Patterns":

    http://www.amazon.com/exec/obidos/tg...books&n=507846

    It seemed like a really interesting and easy to read book, although it's written for Java. If you note that an "interface" in Java is the same thing as a pure abstract class in C++(i.e. a class with all virtual functions and no definitions for the funtions), then you should be able to understand at least the first chapter if you want to take a look at it in the bookstore some time.
    Last edited by 7stud; 11-16-2005 at 07:34 PM.

  7. #7
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    Lol, Havn't read through it yet, but....

    Inheritence with ducks - Cute

  8. #8
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    Ahh.....STL is a beautiful thing.

    A lifesaver.

  9. #9
    Registered User
    Join Date
    Jun 2005
    Location
    Stockholm, Sweden
    Posts
    64
    As long as your life doesn't depend on having any spare RAM

  10. #10
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    The idea behind the design of the Duck class structure:

    1) The designer first used straight inheritance, and the Duck base class implemented the speak() function to quack. The derived classes all inherited the same speak() function. The problem: not all Ducks speak() the same, RubberDuck's don't quack, they squeak.

    2) The designer quickly made some changes to the Duck class to make speak() a virtual function and had each Derived class override speak() to get the proper noise for each species of Duck. Mallards would quack and RubberDuck's would squeak. The problem: if you anticipate having to alter the the noise each Duck makes in the future, you have to dig through every derived Duck class and make the specific changes to the overriding functions. If there are a lot of derived Duck classes, that can be a real chore to maintain.

    3) The resulting design is one that extracts the methods that the programmer anticipates will require alteration in the future, i.e. speak(). That method was extracted from the Duck class and made into separate Quack and Squeak classes. Then each derived Duck class contains a member that is a Quack or Squeak object which represents the sound they make.

    Future changes to the speak() methods will be much easier to maintain because they can be altered in the set of classes that represent the sounds ducks make, i.e. Quack and Squeak, and all of the Duck species that contain those objects will automatically reflect the changes. If you end up having 30 different noises that Duck's make, it will still be a pain to alter all 30 noises if that is required--but that's better than having to go through potentially 100's of derived Duck classes and changing the overridden speak() function in each one of them.

    Quack and Squeak were also given a common base class Sound so that a Sound base class pointer could be used to point to both Quack and Squeak objects. Then, using the base pointer to call speak() results in the appropriate version of speak() being called (that's what "polymorphism" is all about!). The operateDuck() function demonstrates how that works.
    Last edited by 7stud; 11-16-2005 at 07:31 PM.

  11. #11
    xhi
    xhi is offline
    !anExpert
    Join Date
    Mar 2005
    Location
    pa
    Posts
    155
    the duck example is a good one. i have found that it is alot easier to demonstrate oop with the same type of small programs with several simple classes....

    this professor i had once (who i think smoked a ton of crack before every class) anyhow though, he said that oop is like garbage and recycling in that you reduce, reuse, recycle... ?? yeh i dont know either.. but he went on...

    reduce - keep your classes small and specialized, and the member functions specialized. if it looks like it is getting bloated, it probably is

    reuse - you need to design with reuse, interuse in mind. just like in the duck example, inheritance and implicit casts(to base classes) are quite important for easy development

    recycle - this really didnt have an answer. he just said it sounded good. someone asked him if it meant using delete, he said no, and that was the end of that..

    hopefully you are as confused as I am now... lol.. the best way to figure it out is to make a bunch of classes that do nothing but print a little message and start creating derived classes, and creating functions that take a base class, make some virtual functions, play around with multiple inheri... etc... see what they do.. but do this with small classes... its too tempting to get into a big program and then you are just changing this and that until it works without really knowing what is going on....

  12. #12
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    Question, why do we virtualize functions? What does this accomplish? Forgive me for my noobness in C++.

    Nevermind, answered that question:

    A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.
    MSDN 4tw

    Also, with this bit of code, are we just connecting Mallard to the parent class Duck?

    Code:
    class Mallard : public Duck
    Last edited by Shamino; 11-17-2005 at 02:18 AM.

  13. #13
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,801
    1.When you vitualize functions that means the derivied class function with the same name will overwrite the base class function.

    2. You are inheriting publicly from the Duck class which basically means you don't change any of the data hiding from the base class. If you were to say make it protected Duck. Only the class and derivied classes that derivied could call the public functions in the base class.
    Woop?

  14. #14
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    So in theory, if it was protected, If I had a stick (another object)and poked the Mallard, it wouldn't quack, because only duck can make it quack :d

    And another thing. What if we wanted the duck class to hold a few more things, such as, male/female, color, etc...?

    Do we make virtual functions for these that will be overridden by classes that inherit duck? Or do we just create variables for these, since they don't actually function, they just declare an amount?
    Last edited by Shamino; 11-17-2005 at 02:33 AM.

  15. #15
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Hi,

    Here is a scaled back demonstration of what polymorphism is:

    Code:
    #include<iostream>
    #include<vector>
    using namespace std;
    
    class Duck
    {
    public:
    	virtual void speak()
    	{
    		cout<<"I'm a Duck."<<endl;
    	}
    };
    
    class Mallard : public Duck
    {
    public:
    	virtual void speak()
    	{
    		cout<<"Quack, quack."<<endl;
    	}
    };
    
    class RubberDuck : public Duck
    {
    public:
    	virtual void speak()
    	{
    		cout<<"Squeak, squeak"<<endl;
    	}
    };
    
    
    void operateDucks(vector<Duck*> Ducks)
    {
    	for(int i=0; i<Ducks.size(); i++)
    	{
    		//This is where the interesting stuff happens:
    		Ducks[i]->speak(); 
    	}
    }
    
    int main()
    {
    	Duck aDuck;
    	Mallard myDuck;
    	RubberDuck yourDuck;
    	
    	//Put their addresses in a vector(which is like an array):
    	vector<Duck*> Ducks;
    	Ducks.push_back(&aDuck);
    	Ducks.push_back(&myDuck);
    	Ducks.push_back(&yourDuck);
    
    	operateDucks(Ducks);
    
    	return 0;
    }
    If you look at the output from the program, you will see that somehow the operateDucks() function was able to call the correct version of the speak() function for each pointer in the vector--even though all the pointers in the vector are Duck pointers.

    Why didn't the function call the version of speak() in the Duck class everytime? The answer is polymorphism. If you delete the keyword virtual in front of the speak() function in the Duck class, see what happens.
    Last edited by 7stud; 11-17-2005 at 03:06 AM.

Page 1 of 3 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why C++ is not OOPS
    By noobcpp in forum C++ Programming
    Replies: 13
    Last Post: 10-20-2008, 01:20 PM
  2. lol need some help :D
    By lolol in forum C Programming
    Replies: 28
    Last Post: 03-28-2008, 07:46 AM
  3. Oops, she did it again...
    By gcn_zelda in forum A Brief History of Cprogramming.com
    Replies: 1
    Last Post: 09-19-2004, 02:34 PM
  4. lol, funniest acting program EVER -- and i need help with it :(
    By Leeman_s in forum Windows Programming
    Replies: 1
    Last Post: 01-09-2003, 06:27 PM
  5. Lol!
    By no-one in forum A Brief History of Cprogramming.com
    Replies: 24
    Last Post: 02-11-2002, 11:29 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21