C ++ inheritance problem

Here are my classes:

ParentClass, ParentObj

DerivedClass (inherits from ParentClass), DerivedObj (inherits from ParentObj).

ParentClass has a protected element:

std :: vector <ParentObj *>

DerivedClass only selects DerivedObj * objects for this vector.

Problem:

When I use ParentClass, I want to access its vector objects using an iterator like:

std :: vector <ParentObj *> :: const_iterator

And when I use DerivedClass, I want to access its vector objects using an iterator like:

std :: vector <DerivedObj *> :: const_iterator

How can I make it work?

+4
source share
5 answers

You can use virtual override in the DerivedClass class that returns a subtype of the return type ParentClass ...

 struct ParentClass { virtual ParentObj* get( const size_t index ) { return m_objects[index]; } }; struct DerivedClass : public ParentClass { virtual DerivedObj* get( const size_t index ) { return dynamic_cast<DerivedObj*>( ParentClass::get(index) ); } }; 

Both functions are the same vtable entry, although their return type is different.

Alternatively, you can use the same method to create "inherited" iterators.

Also, it would be nice to have the DerivedObj* vector in the DerivedClass object if you guarantee that they are also present in the ParentClass vector.

+4
source

I have a question: why does DerivedClass inherit from ParentClass ?

Do you need polymorphic behavior or want to reuse the ParentClass implementation?

Inheritance is often poorly used. Actually.

Then there is a (typical) problem of having a container class and how to display its elements. Unfortunately, iterators (despite all their products) are poorly supported by the language, unlike pointers, which they must imitate.

So, a reminder: Inheritance is is-a , there is Composition for code reuse.

Here you can write a great class of templates that will play the role of a container and provide common methods.

Then, for the presentation task ... you can write your own iterators with the right base-dependent relationship, or you can select the preliminary selection of several algorithms ( sort , foreach , erase_if ) that will work with predicates provided by the user.

 template <class Value> class Container { public: template <class Pred> void sort(Pred iPred); template <class Pred> Pred foreach(Pred iPred); // maybe a const-version ? template <class Pred> size_t erase_if(Pred iPred); // returns the number of erased private: std::vector<Value> m_data; }; 

Then to your classes:

 class ParentClass { public: virtual void foo() const; private: Container<ParentObj*> m_data; }; class DerivedClass: public ParentClass { public: virtual void foo() const; private: Container<DerivedObj*> m_data; }; 

Try to separate polymorphism from code reuse, and the problem should be simpler.

+2
source

std::vector< ParentObj* > and std::vector< DerivedObj* > are two completely different types, so you cannot implicitly convert one into the other. What you can do is convert each ParentObj* to DerivedObj* using dynamic_cast . But overall, this is not considered good practice.

+1
source

You cannot do this using basic C ++ inheritance. The reason is that the compiler does not know that the vector contains only pointers to DerivedObj when used in DerivedClass . I am the second Naveens dynamic cast operator.

You can use two vectors std::vector< ParentObj* > mParent and std::vector< DerivedObj* > mDerived and a virtual Add() function. The base implementation will only add to mParent . The Add function in DerivedClass will also add to mDerived .

ParentClass will have a GetParentIterator() function, and DerivedClass will have a different (optional) GetDerivedIterator() function.

+1
source

Your inheritance design is incorrect.

DerivedClass should not inherit from ParentClass . ParentClass has a protected element std::vector< ParentObj* > . And DerivedClass must have another protected member std::vector< DerivedObj* > .

You can create a template class

 template<class T> struct MyClass { protected: std::vector< T* > m_objects; }; struct ParentClass : MyClass <ParentObj> {}; struct DerivedClass: MyClass <DerivedObj> {}; 
-one
source

All Articles