исключение std :: bad_cast, генерируемое dynamic_cast

0

в коде ниже, я получаю std::bad_cast исключения брошенного при заливке derived.properties_ из BaseProperties в DerivedProperties. Если посмотреть на код, мне кажется, что что-то не так, когда intialising BaseProperties ссылается на DerivedProperties в конструкторе Base класса.

То, что я пытаюсь достичь, - это простой интерфейс, где Base по сути является моим интерфейсом Component, а Derived - это все, что считается Компонентом. Похоже, справедливое предположение, что Компоненты могут иметь разные свойства, но имеют некоторые аналогичные, такие как размер и положение.

Может ли кто-нибудь предложить какие-либо предложения относительно того, как наилучшим образом достичь моей цели?

#include <iostream>
#include <string>

// Properties for all objects of Base type
class BaseProperties {
public:
  BaseProperties( std::string baseProperty ):
    baseProperty_( baseProperty ) { }

  virtual ~BaseProperties(  ) {  }
  std::string getBaseProperty(  ) { return baseProperty_; }

protected:
  std::string baseProperty_;
};

// Properties specific to objects of Derived type
class DerivedProperties: public BaseProperties {
public:
  DerivedProperties( std::string baseProperty, std::string derivedProperty ):
    BaseProperties( baseProperty ),
    derivedProperty_( derivedProperty ) {  }

  std::string getDerivedProperty(  ) { return derivedProperty_; }

private:
  std::string derivedProperty_;
};

class Base {
public:
  Base( BaseProperties& properties ):
    properties_( properties ) {  }

  virtual ~Base(  ) {  }

protected:
  BaseProperties& properties_;
};

class Derived : public Base {
public:
  Derived( DerivedProperties properties ):
    Base( properties ) {  }

  friend std::ostream & operator << ( std::ostream& out, const Derived& derived );
};

std::ostream & operator << ( std::ostream& out, const Derived& derived ) {  
  return out << derived.properties_.getBaseProperty(  ) << ", "
             << dynamic_cast< DerivedProperties& >( derived.properties_ ).getDerivedProperty(  );
}

int main(  ) {
  Derived derived( DerivedProperties( "BaseProperty", "DerivedProperty" ) );

  std::cout << derived << std::endl;
  return 0;
}
  • 2
    Вы храните ссылку на временный. В какой-то момент один из ваших классов должен стать владельцем DerivedProperties вы передаете.
  • 0
    Не имеет прямого отношения к проблеме, но, возможно, она все еще полезна: обратите внимание, что необходимость делать dynamic_cast здесь кажется подозрительной. Вы не должны требовать производного свойства в контексте, где у вас есть доступ только к базовому свойству. Либо предоставьте виртуальный интерфейс, который позволит вам решить задачу, просто используя базовое свойство, либо сделайте производное свойство напрямую доступным в контексте, где это необходимо. Обращение к dynamic_cast почти всегда является худшим вариантом.
Показать ещё 4 комментария
Теги:
polymorphism
inheritance
c++03

2 ответа

2
Лучший ответ

Ваш производный класс должен взять параметр DerivedProperty& as, аналогичный тому, как это делает ваш базовый класс:

class Derived : public Base {
public:
  Derived( DerivedProperties& properties ):
    Base( properties ) {  }

  friend std::ostream & operator << ( std::ostream& out, const Derived& derived );
};

Поскольку вы не принимаете ссылку как параметр конструктора, а фактический объект, вы фактически храните ссылку на временный объект, который больше не существует после выхода конструктора.

  • 0
    Я надеялся передать его как объект, чтобы устранить необходимость в const DerivedProperties& что означало, что я не смог создать Derived с Derived d( DerivedProperties( "PropertyOne", "PropertyTwo" ) ) . Однако, похоже, что это единственный способ сделать это без полной доработки.
  • 0
    На самом деле, если вы измените тип на const BaseProperties& в обоих конструкторах и в объявлении properties_ , должно работать создание экземпляра Derived с: Derived d( DerivedProperties( "PropertyOne", "PropertyTwo" ) ) . Конечно, это зависит от того, являются ли const-свойства приемлемыми в вашем случае.
Показать ещё 2 комментария
1

Когда конструктор Derived завершится, аргумент properties будет уничтожен. Однако вы сохранили ссылку на этот объект, так что ссылка теперь остается болтающейся. Вместо этого вы должны сделать элемент properties_ не ссылкой.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню