Here are my classes:
ParentClass, ParentObj
DerivedClass (inherits from ParentClass), DerivedObj (inherits from ParentObj).
ParentClass has a protected member:
std::vector< ParentObj* >
DerivedClass allocates only DerivedObj* objects to this vector.
Problem is:
When I use ParentClass, I want to access its vector objects with an iterator of type:
std::vector< ParentObj* >::const_iterator
And when I use DerivedClass, I want to access its vector objects with an iterator of type:
std::vector< DerivedObj* >::const_iterator
How can I make it work?
You can use a virtual override in your DerivedClass
class returning a subtype of the ParentClass
return type...
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, though their return type differs.
Alternatively, you may use the same technique to create 'inherited' iterators.
Next to that, it's not a bad idea to have a vector of DerivedObj*
's in the DerivedClass
object, as long as you guarantee that they are also present in the ParentClass
's vector.
I have a question there: Why does DerivedClass
inherits from ParentClass
?
Do you need a polymorphic behavior, or do you want to reuse the implementation of ParentClass
?
Inheritance is often badly misused. Really.
Then there is the (typical) problem of having a container class, and how to expose its elements. Unfortunately the iterators are (despite all their goods) poorly supported by the language unlike the pointers they are supposed to emulate.
So, a reminder: Inheritance is a is-a relationship, for code reuse there is Composition .
Here you could perfectly write a template class that would play the part of the container and provide common methods.
Then, for the problem of exposition... you can write your own iterators, with the correct base-derived relationship, or you can opt to preselect a number of algorithms ( sort
, foreach
, erase_if
) that would work with user-supplied predicates.
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, on 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 get simpler.
std::vector< ParentObj* >
and std::vector< DerivedObj* >
are two totally different types hence you can not implicitly convert one to another. What you can do is convert each ParentObj*
to DerivedObj*
using dynamic_cast
. But generally it is not considered a good practice.
You can't do that using basic C++ inheritance. The reason is that the compiler doesn't know that the vector contains only pointers to DerivedObj
when used in DerivedClass
. I second Naveens statement about dynamic cast.
You could use two vectors std::vector< ParentObj* > mParent
and std::vector< DerivedObj* > mDerived
and a virtual Add()
function. The base implementation would add only to mParent
. The Add
function in DerivedClass
would also add to mDerived
.
ParentClass
would have a GetParentIterator()
function and DerivedClass
would have another (additional) function GetDerivedIterator()
.
Your inheritance design is wrong.
DerivedClass
must not inherit from ParentClass
. ParentClass
has a protected member std::vector< ParentObj* >
. And DerivedClass
must have another protected member std::vector< DerivedObj* >
.
You may create template class
template<class T>
struct MyClass {
protected:
std::vector< T* > m_objects;
};
struct ParentClass : MyClass <ParentObj> {};
struct DerivedClass: MyClass <DerivedObj> {};
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.