简体   繁体   中英

polymorphism c++, trying to access member functions of classes that are derived from abstract base class

so I have 5 classes,

  1. cds
  2. dvds
  3. books
  4. Item
  5. Inventory

My Item class is an abstract base class and cds,dvds, and books are derived from it. My Inventory class has an array of pointers of the Items type that point towards objects of cd,dvd, and books.

Here is the array:

Item* ptrItems[100];
int totalItems = 0`

Here is how assign an object to the array inside my Inventory class:

ptrItems[totalItems++] =  new books(1000 + totalItems, quantity, tempTitle,tempAuthor, tempDesc, cost);

//I use total items as a counter to keep track of the index

The problem that i have is that ptrItems[totalItems] can not access the member functions of the derived classes only the member functions of the Items abstract class.

For example:

ptrItems[i]->getQuantity() //works fine because getQuanty is a member function of abstract base class Item.

however,

ptrItems[i]->getBookTile() // won't work
error C2039: 'getBookTile' : is not a member of 'Item'  

Correct me if I'm wrong but isn't this polymorphism? It should have access to the derived classes public member functions, right?

You need to convert the Item* pointer to a Books* pointer first

Books * ptrBooks = dynamic_cast<Books*>(ptrItems[i]);

if(ptrBooks)
{
    ptrBooks->getBookTitle();
}

It's important to check that the value of ptrBooks is non zero, as if the pointer to Item passed to dynamic_cast is not pointing to a Books object, it will return zero. This is a way of testing the type of derived object from a base pointer.

No, what you are trying to do is not polymorphism. It is actually the exact opposite of polymorphism.

Polymorphism is using only your base class interface to manipulate any of your derived classes, including those that are not written yet.

For example, if you want your items to have titles, you define a virtual (possibly pure) method getTitle() in your base class, and implement it in your derived classes. This way you can get a title of any item in your collection without knowing or caring about its exact type.

I would strongly suggest to rethink the design. Polymorphism is all about treating potentially different thinks in the same way, and you try to do the opposite. There are ways to do this, eg dynamic_cast , but this is often a sign of a bad design and it should be avoided.

It looks as if your objects are more or less data objects. As a first step, try to think assign operations to the objects and not just methods that return some member variable such as getBookTile() . Then, put the common part of these services in the base class, and use abstract methods called in the common implementation to supply the subtype-specific parts.

For the immediate problem, and if you really want to go that way, the one solution would be to use a dynamic_cast :

dynamic_cast<books*>(ptrItems[i])->getBookTitle();

You may also want to check out std::vector as a better replacement for C-style arrays. And replace the plain pointer by some smart pointer, eg std::shared_ptr or std::unique_ptr , depending on your ownership relation.

Item will have no way of knowing whether or not every Item will have a method getbookTitle() and in this case it seems quite clear they do not. Assume you have an array of Items and not all Items are Books. Then you would run into trouble. Due to this inconsitency it is not allowed with such a method call in c++. A way around this would be to do a dynamic cast as stated in galinettes answer. However, you typically does not want to do this too many times in your code. It will get messy and require a lot of extra checks (unnecessary in this case as you will see). Code with a lot of casting is often a sign of a design flaw somewhere.

However, in this case I can assume that all the objects will have a title . Then it is possible to declare a virtual mehtod in the base class.

virtual string title() = 0; //Pure virtual

this method will have to be implemented in all the derived classes. Now the method can be seen in the base class and all the classes derived from this base class will have to implement this method. The compiler knows the method is virtual and will thus search in the class hierachy to find the right implementation. Now it is possible to call

ptrItems[i] -> title();

A short description can be seen in,

http://www.cplusplus.com/doc/tutorial/polymorphism/

Further, to simplify memory management and for cleaner code, prefer a range checked container such as std::vector unless you have a good reason.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM