Thread: Inheritance and Array question

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    25

    Inheritance and Array question

    My question is that can you put objects from several different objects into an array of pointers from a base class?(i think the answer is yes b/c its an array of pointers) and how would you access data from the derived class?

    for ex.(Illustrative code)
    Code:
    class ComplexShape 
    {
    public: BasicShape *pBasicShape[100];
    ...
    ...
    }
    
    class BasicShape : public ComplexShape 
    {
    public: int someInt;
    ...
    ...
    }
    
    class triangle : public BasicShape
    {
    public : int base
    ...
    ...
    }
    how would i access base if i were to put a pointer to a triangle in '[1]' ?
    ive tried something like this(below), but doesnt work:
    Code:
    ComplexShape Z;
    Z.pBasicShape[1] = new triangle; //assume a default constructor is provided
    Z.pBasicShape[1]->base = 10;
    Last edited by I BLcK I; 12-21-2006 at 01:02 PM.

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    You array of pointers is of type Shape however a triangle is derived from BasicShape and ComplexShape. Is a triangle supposed to be derived from Shape as well and if so why isn't that represented? In order for this to work, a triangle must be deriveable from a Shape object. The overall representation of your classes and the hierarchy they represent seems a little off.
    "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

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    An array of pointers does the trick.

    To access data (or member functions) in derived classes that are not part of the base class, it is necessary to (a) have an instance of the derived class (b) know it is of the derived class (c) if you have a pointer to base, convert it to a pointer to that derived class and (d) access the member you need to.

    In your example, this means that (a) Z.pBasicShape[1] would need to be a triangle (b) your code your need to know that (c) Z.pBasicShape[1] would need to be converted to a pointer to triangle, and (d) the base member of that triangle would need to be accessed. You have not done that, so the compiler has no way of knowing that Z.pBasicShape[1] is a triangle, and therefore does not know it contains a data member named base.

    In code the things you need to do would be;
    Code:
       triangle *temp;
       temp = dynamic_cast<triangle *> (Z.pBasicShape[1]);   // attempt to convert the pointer to a triangle, assuming Shape is a polymorphic base class
    
       if (temp != NULL)   // the conversion has succeeded
           temp->base = 10;
       else
           the_shape_is_not_a_triangle();
    Having to do this is poor design practice. It is better to provide core functionality in the base class, which is tailored by derived classes (eg overriding of a virtual member function) rather than adding functionality to a derived class that does not exist in the base class.

    Incidentally, for your example to make sense at all, triangle needs to be derived from Shape, not from BasicShape.
    Last edited by grumpy; 12-21-2006 at 07:13 AM.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    25
    whoops
    Code:
    Shape *pBasicShape[100];
    should be:
    Code:
    BasicShape *pBasicShape[100];
    Quote Originally Posted by grumpy
    An array of pointers does the trick.

    To access data (or member functions) in derived classes that are not part of the base class, it is necessary to (a) have an instance of the derived class (b) know it is of the derived class (c) if you have a pointer to base, convert it to a pointer to that derived class and (d) access the member you need to.

    In your example, this means that (a) Z.pBasicShape[1] would need to be a triangle (b) your code your need to know that (c) Z.pBasicShape[1] would need to be converted to a pointer to triangle, and (d) the base member of that triangle would need to be accessed. You have not done that, so the compiler has no way of knowing that Z.pBasicShape[1] is a triangle, and therefore does not know it contains a data member named base.

    In code the things you need to do would be;
    Code:
       triangle *temp;
       temp = dynamic_cast<triangle *> (Z.pBasicShape[1]);   // attempt to convert the pointer to a triangle, assuming Shape is a polymorphic base class
    
       if (temp != NULL)   // the conversion has succeeded
           temp->base = 10;
       else
           the_shape_is_not_a_triangle();
    Having to do this is poor design practice. It is better to provide core functionality in the base class, which is tailored by derived classes (eg overriding of a virtual member function) rather than adding functionality to a derived class that does not exist in the base class.

    Incidentally, for your example to make sense at all, triangle needs to be derived from Shape, not from BasicShape.
    didnt think of a dynamic type cast i think thats what i will need to do. and I am using a polymorphic base class. thnxs for the help, ill try this out in a bit
    Last edited by I BLcK I; 12-21-2006 at 01:11 PM.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    25
    What I'm really writing is a basic test inventory program. i just tried to dynamically cast but its not right

    Inventory.h:
    Code:
    #include "InventoryItem.h"
    #include "String.h"
    using namespace std;
    class Inventory
    {
    private:
    	int N;
    	InventoryItem* pI[1000];
    public: 
    	Inventory(): N(0){};
    	~Inventory(){
    		for(int i = 0; i < N; i++)
    		{delete pI[i];}
    	}
    	void createBook(String t, float c, int oH, String aN, String d){
    		pI[N] = new Book(t, c, oH, aN, d);
    		pI[N] = dynamic_cast<Book*>(pI[N]);
    		N++;
    	}
    
    	void createTape(String t, float c, int oH, float pT){
    		pI[N] = new Tape(t, c, oH, pT);
    		pI[N] = dynamic_cast<Tape*>(pI[N]);
    		N++;
    	}
    	
    	void createCd(String t, float c, int oH, int nT, float pT){
    		pI[N] = new Cd(t, c, oH, nT, pT);
    		pI[N] = dynamic_cast<Cd*>(pI[N]);
    		N++;
    	}
    
    	void addItem();
    	void receiveOrder();
    	void report();
    	void sell();
    	void sellPrice();
    	int getN(){return N;}
    };
    Small part of Inventory.cpp
    Code:
    void Inventory::sell()
    {
    	int temp;
    	cout << "Enter in the item number you wish to sell: ";
    	cin >> temp;
    	if ( temp > N ) {cout << "Invalid Item number";}
    	else
    	{
    		int quantity;
    		cout << "How many do you wish to sell: ";
    		cin >> quantity; 
    		if (quantity > pI[temp]->onHand)   // any sort of call like pI[temp]->onHand will not work  ***compiler error here***
    		{cout<<"Unable to sell: " << quantity - onHand << " too many to sell!"<<endl;}
    		else
    		{
    			float temp = pI[temp]->sellPrice() * quantity * 1.0725F;
    			pI[temp]->onHand -= quantity;            //
    			cout << quantity << " Have been sold for " << temp << endl; 
    		}//end 2nd else
    	}//end 1st else
    }
    InventoryItem.h :
    Code:
    #ifndef InventoryItem_H
    #define InventoryItem_H
    
    #include "String.h"
    using namespace std;
    
    class InventoryItem 
    {
    public:
    	//virtual void receiveOrder() = 0;
    	virtual float sellPrice() = 0;
    };
    
    class Book : public InventoryItem
    {
    private:
    	String title;
    	float cost;
    	int onHand;
    	String authorName;
    	String description;
    public:
    	Book() : title(""), cost(0.0), onHand(0.0), authorName(""), description(""){}
    	Book(String t, float c, int oH, String aN, String d) : 
    		title(t), cost(c), onHand(oH), authorName(aN), description(d){}
    	float sellPrice();
    };
    
    class Tape : public InventoryItem
    {
    private:
    	String title;
    	float cost;
    	int onHand;
    	float playTime;
    public:
    	Tape() : title(""), cost(0.0), onHand(0.0), playTime(0.0){}
    	Tape(String t, float c, int oH, float pT) : 
    		title(t), cost(c), onHand(oH), playTime(pT){}
    	float sellPrice();
    };
    
    class Cd : public InventoryItem
    {
    private:
    	String title;
    	float cost;
    	int onHand;
    	int numTrack;
    	float playTime;
    public:
    	Cd() : title(""), cost(0.0), onHand(0.0), numTrack(0), playTime(0.0){}
    	Cd(String t, float c, int oH, int nT, float pT) :
    		title(t), cost(c), onHand(oH), numTrack(nT), playTime(pT){}
    	float sellPrice();
    };
    #endif
    The dynamic cast lines didnt affect the compiler errors im getting
    Quote Originally Posted by MSVC++
    error C2039: 'onHand' : is not a member of 'InventoryItem'

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    title cost and onHand is in any derived class - move them to the Base class
    you don't need dynamic cast when storing pointers in the base pointers array
    onHand is private - make a functions for modifying it 9they will make a validation before modifying value)
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    0.0 isn't an int.
    Code:
    class Cd : public InventoryItem
    {
    private:
    	String title;
    	float cost;
    	int onHand;
    	int numTrack;
    	float playTime;
    public:
    	Cd() : title(""), cost(0.0), onHand(0.0), numTrack(0), playTime(0.0){}
    	Cd(String t, float c, int oH, int nT, float pT) :
    		title(t), cost(c), onHand(oH), numTrack(nT), playTime(pT){}
    	float sellPrice();
    };
    The same code occurs for every class that inherits from InventoryItem.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inheritance question
    By alexy in forum C++ Programming
    Replies: 16
    Last Post: 11-06-2008, 03:46 PM
  2. struct array's inheritance
    By emorrp1 in forum C Programming
    Replies: 8
    Last Post: 06-27-2008, 05:54 AM
  3. Inheritance and program structure planning please help a newbie
    By ninjacookies in forum C++ Programming
    Replies: 1
    Last Post: 10-23-2005, 12:18 PM
  4. Inheritance and Arrays
    By codegirl in forum C++ Programming
    Replies: 18
    Last Post: 06-06-2003, 12:46 PM
  5. Inheritance vs Composition
    By Panopticon in forum C++ Programming
    Replies: 11
    Last Post: 01-20-2003, 04:41 AM