dynamic_cast help?

Discussion in 'C++' started by hijinks@gmail.com, Nov 13, 2005.

  1. Guest

    I am trying to port a python program into c++ to more learn about
    c++... so i am trying to do a MVC design.. so here is my events

    class Event {
    public:
    Event() {}
    Event(string text) { this->name = text; }

    virtual string getName() { return this->name; }

    string name;
    };

    class PlayerSelEvent : public Event {
    public:
    PlayerSelEvent() {}
    PlayerSelEvent(string text, string player) : Event(text) {
    this->player = player; }

    virtual string getPlayer() { return this->player; }

    string player;
    };


    now here is how a function gets it

    void AppMasterController::Notify(Event *ev) {
    std::cout << "got an event: " << ev->name << std::endl;

    // checking the type
    if (ev->getName() == "Set Player") {
    PlayerSelEvent *nameEvent = dynamic_cast<PlayerSelEvent*>(ev);
    std::cout << "players name is: " << nameEvent->getPlayer() <<
    std::endl;
    }
    }

    no the nameEvent->getPlayer() forces the program to quit due to a run
    time error

    am I doing it right to access the getPlayer() function?? or do I need
    to do something else??

    thanks
    mike
    , Nov 13, 2005
    #1
    1. Advertising

  2. Andre Kostur Guest

    wrote in news:1131859552.209495.290960
    @o13g2000cwo.googlegroups.com:

    > I am trying to port a python program into c++ to more learn about
    > c++... so i am trying to do a MVC design.. so here is my events
    >
    > class Event {
    > public:
    > Event() {}
    > Event(string text) { this->name = text; }


    Should be passing text by const-ref. You're paying for an extra copy,
    and prefer initialization to assignment:

    Event(const string & text) : name(text) {}

    >
    > virtual string getName() { return this->name; }
    >
    > string name;
    > };
    >
    > class PlayerSelEvent : public Event {
    > public:
    > PlayerSelEvent() {}
    > PlayerSelEvent(string text, string player) : Event(text) {
    > this->player = player; }


    Same as above... pass by const-ref, and use initialization.

    >
    > virtual string getPlayer() { return this->player; }
    >
    > string player;
    > };
    >
    >
    > now here is how a function gets it
    >
    > void AppMasterController::Notify(Event *ev) {


    Hmm.. why are you accessing the name member directly in the next line,
    but using the accessor function in the if statement?

    > std::cout << "got an event: " << ev->name << std::endl;
    >
    > // checking the type
    > if (ev->getName() == "Set Player") {
    > PlayerSelEvent *nameEvent = dynamic_cast<PlayerSelEvent*>

    (ev);
    > std::cout << "players name is: " << nameEvent->getPlayer() <<
    > std::endl;
    > }
    > }


    Um, why not simply use the result of the dynamic_cast to find out if it's
    the right type?:

    PlayerSelEvent * nameEvent = dynamic_cast<PlayerSelEvent *>(ev);

    if (nameEvent != NULL)
    {
    std::cout << "player's name is: " << nameEvent->getPlayer() <<
    std::endl;
    }

    >
    > no the nameEvent->getPlayer() forces the program to quit due to a run
    > time error
    >
    > am I doing it right to access the getPlayer() function?? or do I need
    > to do something else??


    You didn't check the return value of the dynamic_cast to find out if it
    succeeded or not.

    You also haven't shown us how these events were created and passed into
    this function (Notify). It may be possible that you're passing in an
    event with the name "Set Player" that isn't actually a PlayerSelEvent.

    Other items... any reason why the getName and getPlayer methods are
    declared virtual? Are you intending subclasses to be able to change the
    behaviour of those methods? Why no virtual destructor? (You haven't
    shown the allocation/deallocation cycle of Events (and its
    descendants)... I suspect you may be allocating a decendant and may be
    deleteing it through the pointer to Event...). And... too much stuff is
    public, like the name and player member variables.
    Andre Kostur, Nov 13, 2005
    #2
    1. Advertising

  3. John Carson Guest

    <> wrote in message
    news:
    > I am trying to port a python program into c++ to more learn about
    > c++... so i am trying to do a MVC design.. so here is my events
    >
    > class Event {
    > public:
    > Event() {}
    > Event(string text) { this->name = text; }
    >
    > virtual string getName() { return this->name; }
    >
    > string name;
    > };
    >
    > class PlayerSelEvent : public Event {
    > public:
    > PlayerSelEvent() {}
    > PlayerSelEvent(string text, string player) : Event(text) {
    > this->player = player; }
    >
    > virtual string getPlayer() { return this->player; }
    >
    > string player;
    > };
    >
    >
    > now here is how a function gets it
    >
    > void AppMasterController::Notify(Event *ev) {
    > std::cout << "got an event: " << ev->name << std::endl;
    >
    > // checking the type
    > if (ev->getName() == "Set Player") {
    > PlayerSelEvent *nameEvent = dynamic_cast<PlayerSelEvent*>(ev);
    > std::cout << "players name is: " << nameEvent->getPlayer() <<
    > std::endl;
    > }
    > }
    >
    > no the nameEvent->getPlayer() forces the program to quit due to a run
    > time error
    >
    > am I doing it right to access the getPlayer() function?? or do I need
    > to do something else??
    >
    > thanks
    > mike


    I don't know for sure what is causing your runtime error. Selected excerpts
    from your code are rarely adequate to identify a problem. We are not
    psychic. You should supply complete compileable code that exhibits the
    problem. Often this will be a simplified version of your original code.

    I will make a couple of points. First, dynamic casting is rarely needed in a
    well written program. You can generally achieve the same effect in a less
    error-prone way using virtual functions. Second, if you are to use dynamic
    casting, then you might as well use all the power that it offers. You seem
    to be duplicating its operation.

    Judging by your code excerpt, you have a function that takes a base class
    (Event) pointer as an argument. If the pointer actually points to a base
    class object, you want the function to output only the name member from the
    base class. If it points to a derived class (PlayerSelEvent) object, you
    want the function to output both the name member from the base class and the
    player member from the derived class.

    The simplest way to do this is with a virtual function, Display, defined as:

    virtual void Display()
    {
    std::cout << "got an event: " << getName() << std::endl;
    }

    in Event and

    virtual void Display()
    {
    Event::Display();
    std::cout << "players name is: " << getPlayer() << std::endl;
    }

    in PlayerSelEvent. Your Notify function is then simply:

    void AppMasterController::Notify(Event *ev)
    {
    ev->Display();
    }

    Incidentally, pev is a much better name for a pointer to an Event than is
    ev.

    If this approach is not possible and you must use dynamic casting, then the
    appropriate function definition is as follows:

    void AppMasterController::Notify(Event *ev)
    {
    std::cout << "got an event: " << ev->name << std::endl;
    PlayerSelEvent *nameEvent = dynamic_cast<PlayerSelEvent*>(ev);
    if (nameEvent)
    {
    std::cout << "players name is: " << nameEvent->getPlayer() <<
    std::endl;
    }
    }

    The point here is that the result of dynamic casting will tell you what is
    being pointed to. If it is a PlayerSelEvent object, then the casting works
    and you get the address of the object. If it is an Event object, then the
    casting fails and nameEvent will be zero, indicating that you should not
    attempt to call nameEvent->getPlayer() (doing so will likely cause a runtime
    error). Incidentally, nameEvent would be better called pnameEvent.

    You seem to be attempting to test what is pointed to yourself by testing for
    a name of "Set Player". If a base class object has this name, then your if()
    condition succeeds, nameEvent becomes zero as a result of the dynamic cast,
    and nameEvent->getPlayer() is then an error.


    --
    John Carson
    John Carson, Nov 13, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. alg

    dynamic_cast<>

    alg, Jul 14, 2003, in forum: C++
    Replies:
    3
    Views:
    475
    Rolf Magnus
    Jul 14, 2003
  2. Dan Noland

    dynamic_cast and references

    Dan Noland, Jul 29, 2003, in forum: C++
    Replies:
    0
    Views:
    492
    Dan Noland
    Jul 29, 2003
  3. Yuming Ma
    Replies:
    1
    Views:
    696
    Jeff Schwab
    Dec 17, 2003
  4. Andreas Sch.

    typeid and dynamic_cast, gcc 3.3

    Andreas Sch., Jan 23, 2004, in forum: C++
    Replies:
    18
    Views:
    1,878
    Janusz Szpilewski
    Jan 29, 2004
  5. Jamie Burns
    Replies:
    11
    Views:
    8,958
    Nick Hounsome
    Jan 29, 2004
Loading...

Share This Page