Thread: polymorphism

  1. #1
    Registered User slaveofthenet's Avatar
    Join Date
    Apr 2003
    Posts
    80

    polymorphism

    I've run into a small problem regarding polymorphism. I have a base class named TTT (tic tac toe), I then have 2 derived classes, OnlineGame, and OfflineGame. At the beginning of the program I make a pointer to TTT, then make it a new OnlineGame or OfflineGame depending on user input. My problem is that OnlineGame will need a function to accept the opponent's IP address. I made said function virtual, but now it's requiring me to declare it inside OfflineGame which is illogical to my design. Is there a better way to do this, or am I stuck defining a SetIPAddress for both classes?

    This is my current code. It works, but I don't like it.
    Code:
    class TTT
    {
    public:
    	TTT();
    	void GetUserMove();
    	bool GameOver();
    	virtual void SetIPAddress(string &addr) = 0;
    	virtual void GetOpponentMove();
    };
    
    class OnlineGame : public TTT
    {
    public:
    	OnlineGame();
    	void SetIPAddress(string &addr);
    	void GetOpponentMove();
    };
    
    class OfflineGame : public TTT
    {
    public:
    	OfflineGame();
    	void SetIPAddress(string &addr);
    	void GetOpponentMove();
    };
    Detailed understanding of language features - even of all features of a language - cannot compensate for lack of an overall view of the language and the fundamental techniques for using it. - Bjarne Stroustrup

  2. #2
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    Try to dynamic_cast your pointer to the online version. If the pointer is NULL, the cast did not work (it was not the online version), and proceed as normal. If the cast worked, then set the IP address.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  3. #3
    Registered User
    Join Date
    Jan 2003
    Posts
    648
    The OfflineGame class has no need for the SetIPAddress function, therefore, only define it in OnlineGame.
    Code:
    class TTT
    {
    public:
    	TTT();
    	void GetUserMove();
    	bool GameOver();
    	virtual void GetOpponentMove();
    };
    
    class OnlineGame : public TTT
    {
    public:
    	OnlineGame();
    	void SetIPAddress(string &addr);
    	void GetOpponentMove();
    };
    
    class OfflineGame : public TTT
    {
    public:
    	OfflineGame();
    	void GetOpponentMove();
    };

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Well, if you want the interface to be the same, why not just put the IP address in some kind of generic Init() function, which is called for both kinds of games?

  5. #5
    Registered User slaveofthenet's Avatar
    Join Date
    Apr 2003
    Posts
    80
    Thanks for the replies. Spark, when I try it that way I get an error.
    Code:
    TTT *Game;
    if (menu_choice() == 2) // Setup for online play
    {
    	Game = new OnlineGame;
    	Game->SetIPAddress(get_ipaddr());
    }
    The error states SetIPAddress() is not a member of TTT, which it isn't as it's only declared in OnlineGame.
    Detailed understanding of language features - even of all features of a language - cannot compensate for lack of an overall view of the language and the fundamental techniques for using it. - Bjarne Stroustrup

  6. #6
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    >> The error states SetIPAddress() is not a member of TTT, which it isn't as it's only declared in OnlineGame.

    Hence the problem. You can't access the members from one class in another class. You can try casting the pointer however using dynamic_cast.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  7. #7
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    See this thread about dynamic_cast: http://cboard.cprogramming.com/showt...threadid=41401

    Note: If you do use dynamic_cast on a reference, do so in a try{ } block.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  8. #8
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Don't see why you need to have SetIPAddress in the base class...it seems that it would work if you just remove it from the base class and the OfflineGame class
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class TTT
    {
    public:
    	TTT(){cout<<"something"; }
    	void GetUserMove();
    	bool GameOver();
    	void GetOpponentMove();
    };
    
    class OnlineGame : public TTT
    {
    public:
     OnlineGame()  {cout<<"constructor";}
    	void SetIPAddress(string &addr);
    	void GetOpponentMove();
    };
    
    class OfflineGame : public TTT
    {
    public:
    	OfflineGame();
    	void GetOpponentMove();
    };
    
    
    void OnlineGame::SetIPAddress (string &addr)
    {
    cout<<"Whatever";
    }
    bool TTT::GameOver()
    {
    cout<<"Whatever" ;
    }
    int main(int argc, char *argv[]) {
        string str = "Hi"  ;
              OnlineGame one;
        one.SetIPAddress(str) ;
         one.GameOver();
        return 0;
    }
    Although I get errors when I don't have the some of the functions do anything
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  9. #9
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    >> Don't see why you need to have SetIPAddress in the base class...it seems that it would work if you just remove it from the base class and the OfflineGame class

    The point is to keep a pointer to an object of the base class, so you can use all/most of the external functionality without regard to which particular derived class you have.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  10. #10
    Registered User slaveofthenet's Avatar
    Join Date
    Apr 2003
    Posts
    80
    Thanks again Zach, but I'm still having problems.
    I changed my code to this:
    Code:
    TTT *Game;
    TTT *p = new OnlineGame;
    Game = dynamic_cast<OnlineGame*>(p);
    if (Game != 0)
    {
    	cout << "Cast Succeeded!\n";
    	Game->SetIPAddress(get_ipaddr());
    }
    And it's still giving me an error about SetIPAddress not being a member of TTT. It's also warning me about using dynamic_cast on a polymorphic type.
    Detailed understanding of language features - even of all features of a language - cannot compensate for lack of an overall view of the language and the fundamental techniques for using it. - Bjarne Stroustrup

  11. #11
    Registered User
    Join Date
    Mar 2002
    Posts
    3
    Try this...

    Code:
    TTT *Game;
      OnlineGame *theGame=dynamic_cast<OnlineGame*>(Game);
      
       if (theGame != 0)
       {
    	cout << "Cast Succeeded!\n";
    	theGame->SetIPAddress(get_ipaddr());
       }

  12. #12
    Registered User
    Join Date
    May 2003
    Posts
    161
    Try this:

    Code:
    OnlineGame *Game;
    TTT *p = new OnlineGame;
    Game = dynamic_cast<OnlineGame*>(p);
    if (Game != 0)
    {
    	cout << "Cast Succeeded!\n";
    	Game->SetIPAddress(get_ipaddr());
    }
    Game must be of 'OnlineGame*' type if you want to use that dynamic_cast<OnlineGame*>

  13. #13
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    I think slaveofthenet wants to avoid creating a pointer to the derived type. I think he/she wants to just use a pointer to the base class, so that later on, he/she only has to have one set of code, rather than code for derived class OnlineGame and code for derived class OfflineGame. But then again, I barely understand deriving as it is.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  14. #14
    Registered User
    Join Date
    May 2003
    Posts
    161
    Originally posted by bennyandthejets
    I think slaveofthenet wants to avoid creating a pointer to the derived type. I think he/she wants to just use a pointer to the base class, so that later on, he/she only has to have one set of code, rather than code for derived class OnlineGame and code for derived class OfflineGame. But then again, I barely understand deriving as it is.
    That's not possible, however, unless the SetIPAddress function is declared in the base class.

    Without declaring a pointer, this (very ugly piece of code) is the only thing that I can come up with:

    Code:
    TTT *p = new OnlineGame;
    
    if (dynamic_cast<OnlineGame*>(p))
    {
      cout << "Cast Succeeded!\n";
      (dynamic_cast<OnlineGame*>(p))->SetIPAddress(get_ipaddr());
    }
    But if you're going to do that, why not just declare a pointer?

    Edit: fixed a typo

  15. #15
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Code:
    class TTT
    {
    public:
    	TTT();
    	void GetUserMove();
    	bool GameOver();
    	virtual void SetIPAddress(string &addr) = 0;
    	virtual void GetOpponentMove();
    };
    
    class OnlineGame : public TTT
    {
    public:
    	OnlineGame();
    	void SetIPAddress(string &addr);
    	void GetOpponentMove();
    };
    
    class OfflineGame : public TTT
    {
    public:
    	OfflineGame();
    	void SetIPAddress(string &addr);
    	void GetOpponentMove();
    };
    This is your problem:

    virtual void SetIPAddress(string &addr) = 0;

    You have set this function up as a pure virtual. In other words since you have not defined the body for SetIPAddress any class that is derived from TTT must define the body for this function. Otherwise the compiler will not have any function to call. If you do not wish to do this then do not set it up as a pure virtual function. My advice:

    • Remove SetIPAddress from the base class totally
    • Place SetIPAddress in OnlineGame only - I would redesign the constructor and class so that the IP would be passed to the constructor which would call private function SetIPAddress.


    You cannot use your current declaration of SetIPAddress without re-defining it in every derived class. You could just remove the =0 from the end of the declaration, but since SetIPAddress has nothing at all to do with TTT game - IMO this would be a design flaw.

    You have created a pure virtual base that cannot be instantiated by itself - only OnlineGame and OfflineGame can be instantiated with your current design.

    If you fail to include SetIPAddress in your derived classes - the compiler will flag an error. You have told the compiler that there is no definition of SetIPAddress because you want the derived class(es) to define it the way they need to. This is why you absolutely must have a definition/body for SetIPAddress in every class derived from TTT.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Polymorphism - "pointers" or "references"?
    By Petike in forum C++ Programming
    Replies: 10
    Last Post: 06-04-2009, 05:06 PM
  2. A C++ program examples showing Polymorphism, please help.
    By MarkSquall in forum C++ Programming
    Replies: 19
    Last Post: 06-06-2008, 04:41 AM
  3. Question on polymorphism
    By 6tr6tr in forum C++ Programming
    Replies: 3
    Last Post: 05-06-2008, 09:05 AM
  4. Replies: 3
    Last Post: 10-31-2005, 12:05 PM
  5. Polymorphism & Overloaded Operators :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 09-13-2002, 08:40 PM