0

in the code below, I get a std::bad_cast exception thrown when casting derived.properties_ from BaseProperties to DerivedProperties. Looking at the code, it seems to me like something is going wrong when intialising the BaseProperties with a reference to the DerivedProperties in the Base class constructor.

What I am trying to achieve is a simple UI where Base is essentially my Component interface and Derived is anything that is considered a Component. It seems like a fair assumption that Components may have different properties but have some similar ones, such as size and position.

Can anyone offer any suggestions as to how best to achieve my aim?

#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; } 
6
  • 2
    You are storing a reference to a temporary. At some point one of your classes needs to take ownership of the DerivedProperties you are passing in. Commented Feb 20, 2014 at 16:13
  • Not directly related to the problem, but maybe it's still helpful: Note that the need to do a dynamic_cast here seems suspicious. You should not require a derived property in a context where you only have access to a base property. Either provide a virtual interface that will allow you to solve the task with just using the base property, or make the derived property directly available in the context where it's needed. Resorting to dynamic_cast is almost always a worse option. Commented Feb 20, 2014 at 16:26
  • @ComicSansMS: At some point I'd still have to use dynamic_cast to make the derived property available. I have a function that returns the property via a dynamic_cast however I ommitted it here to try and keep the code shorter, unless there is another way to do so.. Commented Feb 20, 2014 at 16:31
  • @ctor At some point I'd still have to use dynamic_cast to make the derived property available - Why do you say that? In a proper design, you should almost never have to do a dynamic_cast, even if it's hidden inside some nice getter function. See if you can think about a way that you can avoid the need for the cast in your current program altogether. If you have a hard time figuring it out, consider paying the fellows at CodeReview a visit, they are usually great at helping out with problems like this. Commented Feb 20, 2014 at 16:37
  • @ComicSansMS: The only potential way around a dynamic_cast I can see, is by using a static_cast, since I know the type is what I expect it to be. Commented Feb 20, 2014 at 16:39

2 Answers 2

2

Your derived class should take a DerivedProperty& as parameter, similar to how your Base class does it:

class Derived : public Base { public: Derived( DerivedProperties& properties ): Base( properties ) { } friend std::ostream & operator << ( std::ostream& out, const Derived& derived ); }; 

Since you're not taking a reference as constructor parameter but an actual object, you're actually storing a reference to a temporary object, that does not exist anymore once the constructor has exited.

Sign up to request clarification or add additional context in comments.

4 Comments

My hope for passing it as an object was to eliminate the need for const DerivedProperties& which meant I couldn't create Derived with Derived d( DerivedProperties( "PropertyOne", "PropertyTwo" ) ). However it seems that this is the only way to do it without completely redesigning it.
Actually, if you change the type to const BaseProperties& in both constructors and in the declaration of properties_ , creating a Derived instance with: Derived d( DerivedProperties( "PropertyOne", "PropertyTwo" ) ) should work. Of course, it depends if const properties are acceptable in your case.
Should have said, const properties aren't acceptable as I override any attempt to create a property with 0 height or width, although if I allowed them I could probably get away with const properties so long as I didn't need to ever change them.
Ok. Btw, if you did create a property-containing object that way, you would still have an invalid property reference problem when the BaseProperties instance you pass to the constructor goes out of scope...
1

When the Derived constructor ends, the properties argument will be destroyed. However, you've stored a reference to that object, so that reference is now left dangling. Instead, you should make the properties_ member not a reference.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.