Древовидная структура объектов базового и производного классов в C

#c #binary-tree

#c #двоичное дерево

Вопрос:

У меня есть два класса

 class Base {
   explicit Base();

   virtual void update();
}

class Derived : Base {

  std::shared_ptr<Base> left, right;
   
  explicit Derived(std::shared_ptr<Base> left, std::shared_ptr<Base>);

  virtual void update() override;

  void special_update();

}
  

Я могу создать производный объект из двух указателей на объекты базового класса. Но я также хотел бы создать производный объект из двух указателей на объекты производного класса. Есть хороший способ сделать это?

Комментарии:

1. Вы можете использовать, dynamic_cast чтобы проверить, относится ли left параметр в конструкторе к Derived классу или к какому-либо другому Base классу.

2. Вы знаете, почему используете explicit модификатор в своих конструкторах, или вы просто всегда так делаете?

3. Также: судя по именам классов и разделяемому, update() похоже, что Derived предполагается, что это подкласс Base . Но ваш код этого не показывает. Derived Предполагается, что это подкласс Base или нет?

4. ДА. Я действительно намерен создать производный класс, производный от Base. Я отредактировал код.

5. @AnthonyMBenedict Вы также предполагаете, что это будет частное наследование или общедоступное наследование?

Ответ №1:

Предполагая, что вы намереваетесь Derived быть классом, публично производным от Base , вы ищете, std::static_pointer_cast который может преобразовать std::shared_ptr одного типа в std::shared_ptr другого типа:

 Derived(std::shared_ptr<Derived> left, std::shared_ptr<Derived> right)
  : Derived(
      std::static_pointer_cast<Base>(left),
      std::static_pointer_cast<Base>(right)) {
}
  

Если вы не знали, что тип всегда будет конвертируемым в Base из-за отношений наследования, вы также могли бы использовать std::dynamic_pointer_cast (например, при приведении из Base в Derived ).

Также обратите внимание, что вам, очень, очень вероятно, понадобится иметь virtual ~Base() {} , если вы собираетесь перетаскивать Derived объекты в std::shared_ptr<Base> objects. В противном случае вы, скорее всего, понесете убытки.


Если Derived и Base на самом деле совершенно не связаны, то ответ — нет.


Если у вас частное наследование, вам придется создать свою собственную версию static_pointer_cast :

 // in Derived:
static std::shared_ptr<Base> static_pointer_cast(std::shared_ptr<Derived> constamp; r) noexcept {
    return std::shared_ptr<Base>(r, r.get());
}
  

Комментарии:

1. Нет необходимости использовать приведение для преобразования производного в базовый. return std::shared_ptr<Base>(r, static_cast<Base*>(r.get())); не сработает, вы не можете создать два общих указателя, которые указывают на один и тот же объект, не зная об этом друг друга (вы, возможно, захотите посмотреть на std::enable_shared_from_this это)

2. @n.’местоимения’m. Почему вы это говорите? Обратите внимание, что первым аргументом std::shared_ptr является r исходный объект. Взгляните на документацию для shared_ptr конструктора (8) .

3. Извините, не заметил конструктор псевдонимов.