简体   繁体   English

C ++继承问题

[英]C++ inheritance problem

Here are my classes: 这是我的课程:

ParentClass, ParentObj ParentClass,ParentObj

DerivedClass (inherits from ParentClass), DerivedObj (inherits from ParentObj). DerivedClass(继承自ParentClass),DerivedObj(继承自ParentObj)。

ParentClass has a protected member: ParentClass有一个受保护的成员:

std::vector< ParentObj* > std :: vector <ParentObj *>

DerivedClass allocates only DerivedObj* objects to this vector. DerivedClass仅将DerivedObj *对象分配给此向量。

Problem is: 问题是:

When I use ParentClass, I want to access its vector objects with an iterator of type: 当我使用ParentClass时,我想使用类型的迭代器访问其矢量对象:

std::vector< ParentObj* >::const_iterator std :: vector <ParentObj *> :: const_iterator

And when I use DerivedClass, I want to access its vector objects with an iterator of type: 当我使用DerivedClass时,我想使用类型的迭代器访问其矢量对象:

std::vector< DerivedObj* >::const_iterator 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... 您可以在DerivedClass类中使用虚拟覆盖,返回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, though their return type differs. 两个函数都是相同的'vtable'条目,尽管它们的返回类型不同。

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. DerivedClass ,在DerivedClass对象中有一个DerivedObj*的向量并不是一个坏主意,只要你保证它们也存在于ParentClass的向量中。

I have a question there: Why does DerivedClass inherits from ParentClass ? 我有一个问题: 为什么DerivedClass继承自ParentClass

Do you need a polymorphic behavior, or do you want to reuse the implementation of ParentClass ? 您是否需要多态行为,或者您是否要重用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 . 因此,提醒: 继承是一种is-a的关系,代码重用有成分

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. 然后,对于公开的问题......你可以编写自己的迭代器,使用正确的基础派生关系,或者你可以选择预先选择一些与用户提供的谓词一起使用的算法( sortforeacherase_if ) 。

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. std::vector< ParentObj* >std::vector< DerivedObj* >是两个完全不同的类型,因此您不能隐式地将一个转换为另一个。 What you can do is convert each ParentObj* to DerivedObj* using dynamic_cast . 你可以做的是使用dynamic_cast将每个ParentObj*转换为DerivedObj* But generally it is not considered a good practice. 但一般来说,这不是一个好习惯。

You can't do that using basic C++ inheritance. 你不能使用基本的C ++继承来做到这一点。 The reason is that the compiler doesn't know that the vector contains only pointers to DerivedObj when used in DerivedClass . 原因是编译器在DerivedClass使用时不知道向量仅包含指向DerivedObj指针。 I second Naveens statement about dynamic cast. 关于动态演员的第二个Naveens声明。

You could use two vectors std::vector< ParentObj* > mParent and std::vector< DerivedObj* > mDerived and a virtual Add() function. 你可以使用两个向量std::vector< ParentObj* > mParentstd::vector< DerivedObj* > mDerived和一个虚拟的Add()函数。 The base implementation would add only to mParent . 基本实现只会添加到mParent The Add function in DerivedClass would also add to mDerived . DerivedClassAdd函数也会添加到mDerived

ParentClass would have a GetParentIterator() function and DerivedClass would have another (additional) function GetDerivedIterator() . ParentClass有一个GetParentIterator()函数, DerivedClass有另一个(附加)函数GetDerivedIterator()

Your inheritance design is wrong. 你的继承设计是错误的。

DerivedClass must not inherit from ParentClass . DerivedClass不能从ParentClass继承。 ParentClass has a protected member std::vector< ParentObj* > . ParentClass有一个受保护的成员std::vector< ParentObj* > And DerivedClass must have another protected member std::vector< DerivedObj* > . DerivedClass必须有另一个受保护的成员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> {};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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