в коде ниже, я получаю 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;
}
Ваш производный класс должен взять параметр DerivedProperty&
as, аналогичный тому, как это делает ваш базовый класс:
class Derived : public Base {
public:
Derived( DerivedProperties& properties ):
Base( properties ) { }
friend std::ostream & operator << ( std::ostream& out, const Derived& derived );
};
Поскольку вы не принимаете ссылку как параметр конструктора, а фактический объект, вы фактически храните ссылку на временный объект, который больше не существует после выхода конструктора.
const DerivedProperties&
что означало, что я не смог создать Derived
с Derived d( DerivedProperties( "PropertyOne", "PropertyTwo" ) )
. Однако, похоже, что это единственный способ сделать это без полной доработки.
const BaseProperties&
в обоих конструкторах и в объявлении properties_
, должно работать создание экземпляра Derived
с: Derived d( DerivedProperties( "PropertyOne", "PropertyTwo" ) )
. Конечно, это зависит от того, являются ли const-свойства приемлемыми в вашем случае.
Когда конструктор Derived
завершится, аргумент properties
будет уничтожен. Однако вы сохранили ссылку на этот объект, так что ссылка теперь остается болтающейся. Вместо этого вы должны сделать элемент properties_
не ссылкой.
DerivedProperties
вы передаете.dynamic_cast
здесь кажется подозрительной. Вы не должны требовать производного свойства в контексте, где у вас есть доступ только к базовому свойству. Либо предоставьте виртуальный интерфейс, который позволит вам решить задачу, просто используя базовое свойство, либо сделайте производное свойство напрямую доступным в контексте, где это необходимо. Обращение кdynamic_cast
почти всегда является худшим вариантом.