1

I have 3 classes, the one is base class and the others are the inherited classes from the base class, here are the codes of the classes:

// Event Class
#ifndef EVENT_H
#define EVENT_H

#include <iostream>

namespace Engine
{
    namespace Data
    {
        // base class
        class Event
        {
            public:
                // Class Variable
                int Measure;
                int Beat;
                int Position;

                // This Class that was I mean
                class SampleEvent;
                class TimeEvent;

                // Constructor
                Event(int measure, int beat, int pos);
        };

        // Sample Event Class (inherit to Event Class)
        class Event::SampleEvent : public Event
        {
            public:
            // variable in SampleEvent Class
            int ID;
            float Pan;
            float Vol;

            // Constructor
            SampleEvent(int id, float pan, float vol, int measure, int beat, int pos);
        };

        // Time Event Class (inherit to Event class)
        class Event::TimeEvent : public Event
        {
            public:
            // variable in TimeEvent Class
            double Value;

            // Constructor
            TimeEvent(double value, int measure, int beat, int pos);
        };

        // Constructor of Event
        Event::Event(int measure, int beat, int pos)
        {
            Measure         = measure;
            Beat            = beat;
            Position        = pos;
        }

        // Constructor of Sample Event
        Event::SampleEvent::SampleEvent(int id, float pan, float vol, int measure, int beat, int pos) : Event(measure, beat, pos)
        {
            ID                      = id;
            Pan                     = pan;
            Vol                     = vol;
            Measure         = measure;
            Beat            = beat;
            Position        = pos;
        }

        // Constructor of Time Event
        Event::TimeEvent::TimeEvent(double value, int measure, int beat, int pos) : Event(measure, beat, pos)
        {
            Value                   = value;
            Measure         = measure;
            Beat            = beat;
            Position        = pos;
        }
    }      
}
#endif

Let say, I have 2 variable, SE and TE, SE for SampleEvent and TE for TimeEvent, I just want to insert them to vector, and get them from the vector, here is my current code:

Event::SampleEvent SE = Event::SampleEvent(1000, 0, 0, 10, 10, 10);
Event::TimeEvent TE = Event::TimeEvent(200, 20, 20, 20);
vector<Event> DataEvent;

// insert Event
DataEvent.push_back(SE);
DataEvent.push_back(TE);

// Now I just want to get it back
Event::SampleEvent RSE = DataEvent[0]; // -> Error no suitable user-defined conversion from "Engine::Data::Event" to "Engine::Data::Event::SampleEvent" exists
Event::TimeEvent RTE = DataEvent[0];   // -> Error no suitable user-defined conversion from "Engine::Data::Event" to "Engine::Data::Event::TimeEvent" exists

// And I don't know how to detecting the inheritance Class
// something like if (RSE == Event::SampleEvent) or if (RTE == Event::TimeEvent) @_@
awesoon
  • 32,469
  • 11
  • 74
  • 99
CXO2
  • 628
  • 10
  • 28

3 Answers3

1

I believe you need to cast it to get it back. Because while you can implicitly cast a SampleEvent and TimeEvent to an Event, you cannot do it the other way around implicitly.

You will need to either use a reference of Event or a pointer to Event to get this to work properly with casting.

Using References

*removed* you cannot make a vector reference.

Using Pointers

Event::SampleEvent SE = Event::SampleEvent(1000, 0, 0, 10, 10, 10);
Event::TimeEvent TE = Event::TimeEvent(200, 20, 20, 20);

std::vector<Event*> DataEvent;
// insert Event
DataEvent.push_back(&SE);
DataEvent.push_back(&TE);
// get the events back, note this can throw an exception if you cast incorrectly.
Event::SampleEvent* RSE = (Event::SampleEvent*)DataEvent[0]; 
Event::TimeEvent* RTE = (Event::TimeEvent*)DataEvent[1]; 
/// This also Works using static_cast
//Event::SampleEvent* RSE = static_cast<Event::SampleEvent*>(DataEvent[0]); 
//Event::TimeEvent* RTE = static_cast<Event::TimeEvent*>(DataEvent[1]);  
std::cout << RSE->ID << std::endl;
std::cout << RTE->Value << std::endl;

The output is: 1000 200

For more about casting see this stackoverflow answer.

Community
  • 1
  • 1
Kyle C
  • 1,627
  • 12
  • 25
  • I'm working on a more complete answer that will work. one minute – Kyle C Mar 29 '13 at 17:33
  • It still get error, Using Reference: It error in `DataEvent.push_back(&SE);` and `DataEvent.push_back(&TE);` The error is `initial value of reference to non-const must be an lvalue` Using Pointers give me lot of errors, `no operator "*" matches these operands operand types are: * Engine::Data::Event::SampleEvent (TimeEvent also)` and also 'Identifier "static_pointer_cast" is undefined` there are alot error same with that 2 errors – CXO2 Mar 29 '13 at 17:40
  • Try again with the Using Pointers example, this works on my machine. – Kyle C Mar 29 '13 at 17:41
  • Wow Thankks! it worked, btw do you know how to detect the object whether it SampleEvent object or TimeEvent object? – CXO2 Mar 29 '13 at 17:47
  • 1
    @ChronoCross there are a few different ways to do this, one way that I generally like is creating an enum of the different types and setting that enum on object creation. Then have a getter than returns that Type to you. You can also use dynamic_cast, which the link I posted above shows. Glad I could help. – Kyle C Mar 29 '13 at 17:50
  • wow this helping me, I will create enum for the event, since the event take the `Channel` , `Channel` should be `Note1 ~ Note7` if it SampleEvent and `Channel` should be `BPM`if it was TimeEvent, now I can detect it with enumeration LOL Thanks – CXO2 Mar 29 '13 at 17:55
  • @ChronoCross sure thing, if I really helped you can click the uptick to vote this answer up. Thanks! – Kyle C Mar 29 '13 at 17:58
0

you have a vector

vector<Event> DataEvent;

so you shoud use it this way:

Event E = DataEvent[0];

if you type Event::SampleEvent RSE = DataEvent[0]; then you are not using the ability to point to a subclass with base class pointer, but simply casting object. if you want this cast to succed you have to provide conversion operator, or think about using vector of pointers instead: vector<Event* > DataEvent; then if you want get specific event you may use dynamic_cast<> which will allow you to dynamically get object of subclass only if it is actually this subclass object: remember you can have many different subclasses in your vector under common base class also you need some virtual methods, otherwise types are not considered as polymorphic and you cannot use dynamic_cast<>. it is enough to add

virtual void f(){}

to Event class

4pie0
  • 29,204
  • 9
  • 82
  • 118
  • @@ I changed to vector DataEvent but I can't call dynamic_cast<>, the code: `Event::SampleEvent RSE = dynamic_cast(DataEvent[0]);` and it error in `DataEvent[0]` Error: `the operand of a runtime dynamic_cast must have a polymorphic class type` @_@ – CXO2 Mar 29 '13 at 17:30
  • @ChronoCross yes, it is because you need some virtual methids, otherwise types are not considered as polymorphic – 4pie0 Mar 29 '13 at 18:01
  • And in general, you should try to use virtual functions in the base class to develop a common interface, rather than casting to the derived types and working with them separately. – John McFarlane Mar 29 '13 at 18:30
0

It's not possible to cast an subclass object itsef to a base class object, but rather a reference (like a pointer) to a subclass object can be easily casted to a reference of a base class.

stevedes
  • 46
  • 3
  • If so.. how to do that with using reference? – CXO2 Mar 29 '13 at 17:41
  • dynamic_casting a pointer of derived class to base class is possible. See [Here](http://www.cplusplus.com/doc/tutorial/typecasting/) under the section on dynamic_cast. – stevedes Mar 29 '13 at 17:56