Thread: Accessing methods in unknown derived classes of a known baseclass

  1. #1
    *******argv[] - hu? darksaidin's Avatar
    Join Date
    Jul 2003
    Posts
    314

    Accessing methods in unknown derived classes of a known baseclass

    Hi,

    I want to create a library that contains a class world that can, among other things, hold pointers to entity-objects within a virtual world.

    The entity-class will be defined in a header file for the library. Someone using the library should be able to create his own derived classes of the entity class and register instances of that derived class to the world object (like world->registerEntity(FrogEntity)).
    Using the pointer the world object received from its register method, it should be able to call methods of the derived class of entity.
    It's probably to complicated or not even possible to call methods that were first defined in the derived class, but what about "overwritten" (don't know the term in C) methods. Is there any way I can access those?

    It would be enough to have access to one, overwritten method and then give it instructions to call the other methods.

    I thought about instead of registering a pointer to the object, registering a pointer to the new, overwritten method of the object, but that wouldn't help me either. Now I got the method, but it's not linked to the objects data anymore (I assume that every instance of an object uses the same methods defined by it's class and probably hands over a hidden instance pointer in the parameter list, but how do I do that without modifying the compiler (out of question) ?

    Hopefully you undestand my question/problem. I probably didn't use the right terms

  2. #2
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    You can dictate what functions are available to "world" in the design of "entity"

    IE;
    Code:
    class entity
    {
    public:
    virtual void foo() = 0;
    virtual void bar() = 0;
    };
    If all derived object's came from "entity" they would need to implement void foo() and void bar()...if they didnt, they couldnt be made into an instance of an object....then with an "entity" pointer to a derived object, "world" can call foo() or bar().

  3. #3
    *******argv[] - hu? darksaidin's Avatar
    Join Date
    Jul 2003
    Posts
    314
    Thanks Fordy!

    Code:
    virtual void foo() = 0;
    What does this exactly mean? Is it an abstract function without any implementation in the class? (What does "= 0" mean? [*NULL?])

    If all derived object's came from "entity" they would need to implement void foo() and void bar()...if they didnt, they couldnt be made into an instance of an object....then with an "entity" pointer to a derived object, "world" can call foo() or bar().
    How do I hand over the pointer to an object of an unknown class ? Can I use typecasting to hand it over as entity ? I have so far coded in Delphi. If I used typecasting to convert a derived object of entity back to entity, (I think) all calls done with this pointer would have called the functions from the entity-class itself. Does virtual prevent this?

    Maybe I think too complicated and it's really that simple. Would be great

  4. #4
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    The "=0" means it's a pure virtual function......it means that any class that inherits from it MUST implement that function properly...otherwise you cant make an instance of that object.

    What you can do is make world accept a pointer to an entity (and as you write the base class of entity, it's somthing that world does know about). If you derive all your objects from entity, then they can be addressed via an entity pointer, and as you have designed virtual functions that need to be implemented in each derived class, you also have a way to invoke functions on these derived classes via their entity pointers...

    Here's a quick & dirty example

    Code:
    #include <iostream>
    #include <vector>
    
    //base class
    class entity
    {
    public:
    	//pure virtual function - all derived objects need a WhoAmI object
    	virtual void WhatAmI() = 0;
    };
    
    //world class
    class world
    {
    public:
    	void RegisterObject(entity* e)//ad a pointer to an object to the world
    	{
    		m_vec.push_back(e);
    	}
    	void DoSomethingWithAllObjects()//call WhoAmiI on all objects
    	{
    		for(unsigned int i = 0;i < m_vec.size();++i)
    			(m_vec[i])->WhatAmI();		
    	}
    	void DeleteAllObjects()//Free all objects
    	{
    		for(unsigned int i = 0;i < m_vec.size();++i)
    			delete (m_vec[i]);
    	}
    private:
    	std::vector<entity*> m_vec;//a vector that will act as an array of objects
    };
    
    //derived classes
    class person : public entity
    {
    public:
    	void WhatAmI(){std::cout << "I am a person" << std::endl;}
    };
    
    class dog : public entity
    {
    public:
    	void WhatAmI(){std::cout << "I am a dog" << std::endl;}
    };
    
    class bird : public entity
    {
    public:
    	void WhatAmI(){std::cout << "I am a bird" << std::endl;}
    };
    
    int main(void)
    {	
    
    	world w;
    	//add instances of new derived classes..excuse lack of error checking
    	w.RegisterObject(new person);
    	w.RegisterObject(new bird);
    	w.RegisterObject(new dog);
    
    	w.DoSomethingWithAllObjects();
    
    	w.DeleteAllObjects();
    }
    Not a great example, but it should get the idea across - all you need to realise is that world doesnt know anything about person,bird or dog - it doesnt need to, as long as they all share entity as a base class they can all be manipulated in the same way

  5. #5
    *******argv[] - hu? darksaidin's Avatar
    Join Date
    Jul 2003
    Posts
    314
    Thank you, Fordy. That code helped me a lot!

    There are a few other things I need to find out. I.e. if it's possible to have code in the baseclasses implementation of WhatAmI() that all derived classes will inherit and execute before or after the code that is implemented in their own WhatAmI(), but I think that's something I can figure out by myself.
    However, if thats not possible a little hint would be very welcome

  6. #6
    It's full of stars adrianxw's Avatar
    Join Date
    Aug 2001
    Posts
    4,829
    A class can find out what it is using "Run Time Type Identity", look up the type_info class for example.
    Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream.

  7. #7
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    However, be aware that using RTTI, or dynamic_cast, is circumventing the normal inheritance/polymorphic system of C++, so it's usually a better idea not to try to figure out what an object is at runtime.

    Also, remember to make your base class's destructor virtual.

  8. #8
    *******argv[] - hu? darksaidin's Avatar
    Join Date
    Jul 2003
    Posts
    314
    Originally posted by Cat
    However, be aware that using RTTI, or dynamic_cast, is circumventing the normal inheritance/polymorphic system of C++, so it's usually a better idea not to try to figure out what an object is at runtime.

    Also, remember to make your base class's destructor virtual.
    I don't understand. Why I would use typecasting if it is not neccessary, which it doesn't seem to be when using virtual?

    Anyway, I just found out how to call a baseclass-function that I have "overwritten" (w?) in the derived class. At first I tried to cast the derived class as the baseclass, but that didn't work. After looking through tons of tutorials I found the notation: Baseclass::function I guess I wasn't looking for something that simple

    btw, do I have to call the baseclasses destructor in the derived classes destructor?

    edit: I don't feel like bumping the topic again, but thank you for the reply, cat.
    Last edited by darksaidin; 07-27-2003 at 05:19 PM.

  9. #9
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    virtual is all well and good; it's part of the OOP nature of C++. There are a few cases where virtual functions alone won't cut it -- for example, sometimes you want to access a function in a child class that isn't (and shouldn't be) part of the base class. However, such cases usually are born from poor design choices.

    You do not need to explicitly call the base class destructor, it happens automatically. You DO need to declare the base class as having a virtual destructor, though (just pop that word before the destructor declaration).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Accessing Classes in Classes
    By GrNxxDaY in forum C++ Programming
    Replies: 18
    Last Post: 07-30-2002, 01:54 PM
  2. List of derived classes
    By Asmodan in forum C++ Programming
    Replies: 1
    Last Post: 05-28-2002, 08:46 PM
  3. Replies: 2
    Last Post: 01-15-2002, 06:00 PM
  4. Inheiritance and derived classes
    By pecymanski in forum C++ Programming
    Replies: 2
    Last Post: 12-09-2001, 03:50 PM
  5. Pointers to derived classes.
    By sean in forum C++ Programming
    Replies: 3
    Last Post: 11-13-2001, 08:19 PM