How to build a better diamond?

Discussion in 'C++' started by Steven T. Hatton, Apr 8, 2004.

  1. Below is some code I wrote to get a better understanding of the dynamic
    verses static type resolution. My intention was to see if there was a way
    to use references for the static access to the subobjects of an object of
    derived type. I thought I had seen a way to use references to statically
    access member functions in a way syntactically similar to how pointers
    dynamically access the same objects member functions.

    The overall objective is to 'navigate' the diamond in the most elegant and
    safe way. I had hoped to use this as a follow up to the discussion on
    references and pointers and other objects(sic). Unfortunately I wasn't able
    to find a way to do what I thought I could.

    Do othere people have comments on how best to 'navigate' the class
    hierarchy?

    #include <string>
    #include<iostream>

    using std::string;


    class North
    {
    public:
    North(const string& name="North"):m_name(name)
    {}
    virtual string& toString() { return m_name; }
    private:
    string m_name;
    };

    class East : virtual public North
    {
    public:
    East(const string& name="East"):m_name(name)
    {}
    virtual string& toString()
    {
    string* ret = new string(North::toString());
    *ret += "::";
    *ret += m_name;
    return *ret;
    }
    private:
    string m_name;
    };

    class West : virtual public North
    {
    public:
    West(const string& name="West"):m_name(name)
    {}
    virtual string& toString()
    {
    string* ret = new string(North::toString());
    *ret += "::";
    *ret += m_name;
    return *ret;
    }
    private:
    string m_name;
    };

    class South : public East, public West
    {
    public:
    South(const string& name="South"):m_name(name)
    {}
    virtual string& toString()
    {
    string* ret = new string(East::toString());
    *ret += "::";
    *ret += West::toString();
    *ret += "::";
    *ret += m_name;
    return *ret;
    }
    private:
    string m_name;
    };


    int main()
    {
    using std::cout;
    using std::endl;

    North n;
    East e;
    West w;
    South s;
    cout<<n.toString()<<endl;
    cout<<e.toString()<<endl;
    cout<<w.toString()<<endl;
    cout<<s.toString()<<endl;

    North ns = static_cast<North>(s);
    East es = static_cast<East>(s);
    West ws = static_cast<West>(s);
    cout<<ns.toString()<<endl;
    cout<<es.toString()<<endl;
    cout<<ws.toString()<<endl;
    }

    /*OUTPUT*/
    North
    North::East
    North::West
    North::East::North::West::South
    North
    North::East
    North::West

    --
    p->m == (*p).m == p[0].m
    http://www.kdevelop.org
    http://www.suse.com
    http://www.mozilla.org
     
    Steven T. Hatton, Apr 8, 2004
    #1
    1. Advertising

  2. * "Steven T. Hatton" <> schriebt:
    >
    >
    > #include <string>
    > #include<iostream>
    >
    > using std::string;
    >
    >
    > class North
    > {
    > public:
    > North(const string& name="North"):m_name(name)
    > {}
    > virtual string& toString() { return m_name; }


    Ungood to return reference to internal member here, and should be const
    function to allow calls on const object, thus:


    virtual string toString() const { return m_name; }


    Also, consider a private or protected function name() instead of member;
    the function won't occupy storage per object.


    > private:
    > string m_name;
    > };
    >
    > class East : virtual public North
    > {
    > public:
    > East(const string& name="East"):m_name(name)
    > {}
    > virtual string& toString()
    > {
    > string* ret = new string(North::toString());
    > *ret += "::";
    > *ret += m_name;
    > return *ret;
    > }


    1) The code does not deallocate 'ret'.
    2) It's not exception safe. For exception safe you'd have to use
    std::auto_ptr. But
    3) A better way is 'return North::toString() + "::" + m_name';


    > North::East::North::West::South


    I suggest forgetting that diamond inheritance pattern for a while;
    concentrate on just creating some useful program.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is top-posting such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Apr 8, 2004
    #2
    1. Advertising

  3. Alf P. Steinbach wrote:

    > * "Steven T. Hatton" <> schriebt:
    >>
    >>
    >> #include <string>
    >> virtual string& toString() { return m_name; }

    >
    > Ungood to return reference to internal member here,


    Agreed. I wasn't sure how best to return a copy.

    > and should be const
    > function to allow calls on const object, thus:


    I wasn't sure of the syntax. I tried a couple combination, but they didn't
    compile. I really think I need to get the C++ Pocket Reference. It's hard
    to find good paradigms in the materials I have at hand.

    > virtual string toString() const { return m_name; }


    Thanks for the example.

    > Also, consider a private or protected function name() instead of member;
    > the function won't occupy storage per object.


    I'm not exactly sure what you're suggesting. Is this related to
    std::type_info?


    > 1) The code does not deallocate 'ret'.


    I was aware of that. This is one of the reasons Java's string is immutable.
    It's also why Xerces C++ XMLstring class is such a monster. I guess the way
    to address a situation like this is with handles. I didn't want to get
    that deep into things just yet.

    > 2) It's not exception safe. For exception safe you'd have to use
    > std::auto_ptr. But
    > 3) A better way is 'return North::toString() + "::" + m_name';


    I wasn't sure what that would do. I /believe/ it does about the same thing
    as what I provided, but never creates an explicit pointer. I don't know
    what scoping and lifetime rules apply. If it's allocated as dynamic
    storage (which I believe it will be), the onus is on me to release it when
    I'm finished.

    >
    >> North::East::North::West::South

    >
    > I suggest forgetting that diamond inheritance pattern for a while;
    > concentrate on just creating some useful program.


    The inheritance doesn't seem all that confusing in general. The thing I'm
    really trying to get a handle on through this exercise is how references
    and pointers work WRT overloaded (and hidden) virtual functions. I guess
    that wasn't very obvious since all the code I posted used values rather
    than pointers and references. I figure, if I can keep creating instructive
    and interesting examples based on the pattern of the code I posted, it will
    serve as a way to reinforce the trickier lessons surrounding inheritance.

    As for writing useful programs, that's why I gave up on C++ last time. It
    was too frustrating to know what I wanted to do, but not how to do it. I
    had created the UI shown below with the data elements backed by
    QDomElements. I tried creating another feature using templates and ended
    up so tangled up I just quit.

    http://baldur.globalsymmetry.com/gs-home/images/kgrammar.png

    --
    p->m == (*p).m == p[0].m
    http://www.kdevelop.org
    http://www.suse.com
    http://www.mozilla.org
     
    Steven T. Hatton, Apr 8, 2004
    #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. Jay Dean
    Replies:
    57
    Views:
    26,789
    Arne Vajhøj
    Dec 10, 2013
  2. Alexander Stippler

    virtual inheritance / dreaded diamond problem

    Alexander Stippler, Jul 14, 2003, in forum: C++
    Replies:
    0
    Views:
    1,901
    Alexander Stippler
    Jul 14, 2003
  3. Alexander Stippler

    virtual inheritance / dreaded diamond again

    Alexander Stippler, Aug 26, 2003, in forum: C++
    Replies:
    1
    Views:
    407
    Ron Natalie
    Aug 26, 2003
  4. Tom
    Replies:
    3
    Views:
    513
  5. puzzlecracker

    virtual function, inline, diamond?

    puzzlecracker, Jan 14, 2005, in forum: C++
    Replies:
    3
    Views:
    346
    Alf P. Steinbach
    Jan 14, 2005
Loading...

Share This Page