Two nested classes are tied together.

Discussion in 'C++' started by Nephi Immortal, Aug 12, 2011.

  1. I create one main class. I use three data members to do addition
    between left value and right value through reference. It is the
    standard C++ code as common practice.
    Look at the code below and see my comments.

    class Data
    {
    public:
    Data() : x( 0 ), y( 0 ), z( 0 )
    {
    }

    Data( int _x, int _y, int _z ) : x( _x ), y( _y ), z( _z )
    {
    }

    ~Data()
    {
    }

    Data( const Data &rData ) : x( rData.x ), y( rData.y ), z( rData.z )
    {
    }

    Data &operator=( const Data &rData )
    {
    if( this == &rData )
    return *this;

    x = rData.x;
    y = rData.y;
    z = rData.z;

    return *this;
    }

    Data &operator+=( const Data &rData )
    {
    x += rData.x;
    y += rData.y;
    z += rData.z;

    return *this;
    }

    Data operator+( const Data &rData )
    {
    Data temp( *this );
    return ( temp += rData );
    }


    private:
    int x;
    int y;
    int z;
    };

    int main()
    {
    Data d1( 1, 2, 3 ), d2( 4, 5, 6 ), d3( 7, 8, 9 );

    d1 = d2 + d3;

    return 0;
    }


    My code looks fine. I decide to design nested classes inside main
    class. They are inner classes and are hidden from the client. The
    client uses Proxy() function to access nested class’ functions.
    I create two helper classes. Both of them are tied or related
    together. It is necessary because I put reference on data member:
    rData. The Data class remains unmodified through Proxy class’
    reference unless you never place any Object class’ data members inside
    Proxy class or they will be modified.
    I choose reference instead of copy of value because if I add more
    data members in Data class, constructor function will copy all data
    members every time it is called and destroyed. It would be overhead
    on CPU.
    I traced my code through debugger and tested all data members being
    pushed into and popped out of stack in the correct order. Everything
    is working properly.
    How can you assure that my code is NOT undefined behavior?


    class Object
    {
    private:
    class _Proxy;
    class Data
    {
    public:
    Data() : x( 0 ), y( 0 ), z( 0 )
    {
    }

    Data( int _x, int _y, int _z ) : x( _x ), y( _y ), z( _z )
    {
    }

    ~Data()
    {
    }

    Data( const Data &_rData ) : x( _rData.x ), y( _rData.y ),
    z( _rData.z )
    {
    }

    Data &operator=( const Data &_rData )
    {
    if( this == &_rData )
    return *this;

    x = _rData.x;
    y = _rData.y;
    z = _rData.z;

    return *this;
    }

    Data &operator+=( const Data &_rData )
    {
    x += _rData.x;
    y += _rData.y;
    z += _rData.z;

    return *this;
    }

    Data operator+( const _Proxy &_rProxy )
    {
    Data temp( *this );
    return ( temp += _rProxy.rData );
    }

    //private: /* Put Data class inside outer class. */
    int x;
    int y;
    int z;
    };

    Data _data;

    class _Proxy
    {
    public:
    _Proxy( Data &_data ) : rData( _data )
    {
    }

    ~_Proxy()
    {
    }

    _Proxy &operator=( const _Proxy &_rProxy )
    {
    if( this == &_rProxy )
    return *this;

    rData = _rProxy.rData;
    return *this;
    }

    _Proxy &operator=( const Data &_rData )
    {
    rData = _rData;
    return *this;
    }

    _Proxy &operator+=( const _Proxy &_rProxy )
    {
    rData += _rProxy.rData;
    return *this;
    }

    Data operator+( const _Proxy &_rProxy )
    {
    Data temp( rData );
    temp += _rProxy.rData;
    return temp;
    }

    //private: /* Put _Proxy class inside outer class. */
    Data &rData; // Reference
    };

    public:
    Object() : _data( 0, 0, 0 )
    {
    }

    Object( int _x, int _y, int _z ) : _data( _x, _y, _z )
    {
    }

    ~Object()
    {
    }

    Object( const Object &rObject ) : _data( rObject._data )
    {
    }

    Object &operator=( const Object &rObject )
    {
    if( this == &rObject )
    return *this;

    _data = rObject._data;

    return *this;
    }

    _Proxy Proxy() // _Proxy is copy of value
    {
    return _Proxy( _data ); // _data is reference
    }

    };




    int main()
    {
    Object object1, object2( 1, 2, 3 ), object3( 4, 5, 6 ), object4( 7,
    8, 9 ), object5( 10, 11, 12 );

    object1.Proxy() = object2.Proxy() + object3.Proxy() + object4.Proxy()
    + object5.Proxy();

    object2.Proxy() = object3.Proxy();
    object2.Proxy() += object4.Proxy();

    object4 = object1;

    return 0;
    }
     
    Nephi Immortal, Aug 12, 2011
    #1
    1. Advertising

  2. Nephi Immortal

    red floyd Guest

    On 8/12/2011 12:07 AM, Paavo Helde wrote:
    > Nephi Immortal<> wrote in


    >> class Object
    >> {
    >> private:
    >> class _Proxy;

    >
    > Using such a name is UB, so definitely your code has undefined behavior
    > ;-)


    Is it UB, or is the code simply ill-formed?
     
    red floyd, Aug 12, 2011
    #2
    1. Advertising

  3. On Aug 12, 2:07 am, Paavo Helde <> wrote:
    > Nephi Immortal <> wrote innews::
    >
    >
    >
    >
    >
    > >      I create one main class.  I use three data members to do addition
    > > between left value and right value through reference.  It is the
    > > standard C++ code as common practice.
    > >      Look at the code below and see my comments.

    >
    > > class Data
    > > {
    > > public:
    > >      Data() : x( 0 ), y( 0 ), z( 0 )
    > >      {
    > >      }

    >
    > >      Data( int _x, int _y, int _z ) : x( _x ), y( _y ), z( _z )
    > >      {
    > >      }

    >
    > >      ~Data()
    > >      {
    > >      }

    >
    > >      Data( const Data &rData ) : x( rData.x ), y( rData.y ), z(
    > >      rData.z ) {
    > >      }

    >
    > >      Data &operator=( const Data &rData )
    > >      {
    > >           if( this == &rData )
    > >                return *this;

    >
    > >           x = rData.x;
    > >           y = rData.y;
    > >           z = rData.z;

    >
    > >           return *this;
    > >      }

    >
    > >      Data &operator+=( const Data &rData )
    > >      {
    > >           x += rData.x;
    > >           y += rData.y;
    > >           z += rData.z;

    >
    > >           return *this;
    > >      }

    >
    > >      Data operator+( const Data &rData )

    >
    > This should be 'const' or a free function.
    >
    >
    >
    >
    >
    > >      {
    > >           Data temp( *this );
    > >           return ( temp += rData );
    > >      }

    >
    > > private:
    > >      int x;
    > >      int y;
    > >      int z;
    > > };

    >
    > > int main()
    > > {
    > >      Data d1( 1, 2, 3 ), d2( 4, 5, 6 ), d3( 7, 8, 9 );

    >
    > >      d1 = d2 + d3;

    >
    > >      return 0;
    > > }

    >
    > >      My code looks fine.  I decide to design nested classes inside
    > >      main
    > > class.  They are inner classes and are hidden from the client.  The
    > > client uses Proxy() function to access nested class’ functions.
    > >      I create two helper classes.  Both of them are tied or related
    > > together.  It is necessary because I put reference on data member:
    > > rData.  The Data class remains unmodified through Proxy class’
    > > reference unless you never place any Object class’ data members inside
    > > Proxy class or they will be modified.
    > >      I choose reference instead of copy of value because if I addmore
    > > data members in Data class, constructor function will copy all data
    > > members every time it is called and destroyed.  It would be overhead
    > > on CPU.
    > >      I traced my code through debugger and tested all data members
    > >      being
    > > pushed into and popped out of stack in the correct order.  Everything
    > > is working properly.
    > >      How can you assure that my code is NOT undefined behavior?

    >
    > > class Object
    > > {
    > > private:
    > >      class _Proxy;

    >
    > Using such a name is UB, so definitely your code has undefined behavior
    > ;-)
    >
    > If you rename this class, your code seems to OK at the first glance. It
    > is a bit fragile as one must take care that an Object is not destroyed
    > before a corresponding Proxy. I would add some safeguards for such a
    > design, at least in Debug builds, e.g. each Proxy would increase a
    > counter in the Object while it's alive, and the Object's destructor
    > asserts that the counter has reached zero again.


    “If you rename this class”

    I truly do not understand your point. What are you trying to clarify
    that you rename a class name? Please clarify. I don’t see any
    undefined behavior.

    You said Object *possibly* calls destructor function before Data and
    Proxy call destructor function. It does not make any sense. If you
    look at the stack, you will see that Data and Proxy call destructor
    function and are popped out of stack before Object calls destructor
    function.

    Try to test your code. Move Data class and Proxy class outside Object
    class. Define Data variable and Proxy variable in main function. You
    will see nothing is wrong. They are working properly as long as
    undefined behavior never occurs.

    I do not want the client to access Data class and Proxy class
    directly. They are placed inside Object class in private. The
    safeguard is sufficient maximum.

    You do not need to use counter in destructor class unless you want to
    use dynamic array.

    Please answer my question. Notice two functions in Proxy class below.

    Data operator+( const _Proxy &_rProxy )
    Proxy &operator=( const Data &_rData )

    Both Data class and Proxy class are *tied* together.

    If you design single class, the return type and function parameter
    type must be identical.
     
    Nephi Immortal, Aug 12, 2011
    #3
  4. Nephi Immortal

    red floyd Guest

    On 8/12/2011 12:16 PM, Nephi Immortal wrote:
    > On Aug 12, 2:07 am, Paavo Helde<> wrote:
    >> Nephi Immortal<> wrote innews::


    >>> class Object
    >>> {
    >>> private:
    >>> class _Proxy;

    >>
    >> Using such a name is UB, so definitely your code has undefined behavior
    >> ;-)
    >>
    >> If you rename this class, your code seems to OK at the first glance. It
    >> is a bit fragile as one must take care that an Object is not destroyed
    >> before a corresponding Proxy. I would add some safeguards for such a
    >> design, at least in Debug builds, e.g. each Proxy would increase a
    >> counter in the Object while it's alive, and the Object's destructor
    >> asserts that the counter has reached zero again.

    >
    > “If you rename this class”
    >
    > I truly do not understand your point. What are you trying to clarify
    > that you rename a class name? Please clarify. I don’t see any
    > undefined behavior.
    >


    Any identifier with a leading underscore followed by an upper-case
    letter is reserved to the implementation in ANY scope. This means
    that you may not use such identifiers (like _Proxy) for your own
    purposes.

    What Paavo was saying is that outside of this issue, your code
    looks OK.
     
    red floyd, Aug 12, 2011
    #4
  5. On Aug 12, 3:27 pm, red floyd <> wrote:
    > On 8/12/2011 12:16 PM, Nephi Immortal wrote:
    >
    >
    >
    >
    >
    > > On Aug 12, 2:07 am, Paavo Helde<>  wrote:
    > >> Nephi Immortal<>  wrote innews::
    > >>> class Object
    > >>> {
    > >>> private:
    > >>>       class _Proxy;

    >
    > >> Using such a name is UB, so definitely your code has undefined behavior
    > >> ;-)

    >
    > >> If you rename this class, your code seems to OK at the first glance. It
    > >> is a bit fragile as one must take care that an Object is not destroyed
    > >> before a corresponding Proxy. I would add some safeguards for such a
    > >> design, at least in Debug builds, e.g. each Proxy would increase a
    > >> counter in the Object while it's alive, and the Object's destructor
    > >> asserts that the counter has reached zero again.

    >
    > > “If you rename this class”

    >
    > > I truly do not understand your point.  What are you trying to clarify
    > > that you rename a class name?  Please clarify.  I don’t see any
    > > undefined behavior.

    >
    > Any identifier with a leading underscore followed by an upper-case
    > letter is reserved to the implementation in ANY scope.  This means
    > that you may not use such identifiers (like _Proxy) for your own
    > purposes.
    >
    > What Paavo was saying is that outside of this issue, your code
    > looks OK.- Hide quoted text -


    OK. Paavo was saying is that my code is OK. What is he referring
    “OK”? I guess to be the fact as poor design. If you answer yes,
    please clarify why you think that the design is poor? Tell me more
    reasons. Perhaps, you express your opinion.

    I assume. You perhaps say do not use reference on all data members
    and always declare value type or pointer. Explain the reason. Maybe,
    reference is not the option because it leads to undefined behavior.
     
    Nephi Immortal, Aug 13, 2011
    #5
  6. On Aug 12, 3:27 pm, red floyd <> wrote:
    > On 8/12/2011 12:16 PM, Nephi Immortal wrote:
    >
    >
    >
    >
    >
    > > On Aug 12, 2:07 am, Paavo Helde<>  wrote:
    > >> Nephi Immortal<>  wrote innews::
    > >>> class Object
    > >>> {
    > >>> private:
    > >>>       class _Proxy;

    >
    > >> Using such a name is UB, so definitely your code has undefined behavior
    > >> ;-)

    >
    > >> If you rename this class, your code seems to OK at the first glance. It
    > >> is a bit fragile as one must take care that an Object is not destroyed
    > >> before a corresponding Proxy. I would add some safeguards for such a
    > >> design, at least in Debug builds, e.g. each Proxy would increase a
    > >> counter in the Object while it's alive, and the Object's destructor
    > >> asserts that the counter has reached zero again.

    >
    > > “If you rename this class”

    >
    > > I truly do not understand your point.  What are you trying to clarify
    > > that you rename a class name?  Please clarify.  I don’t see any
    > > undefined behavior.

    >
    > Any identifier with a leading underscore followed by an upper-case
    > letter is reserved to the implementation in ANY scope.  This means
    > that you may not use such identifiers (like _Proxy) for your own
    > purposes.


    You refer underscore with name is implementation. I think you refer
    an example -- _Vector_const_iterator and _Vector_iterator. The client
    can’t use either _Vector_const_iterator or _Vector_iterator. He needs
    to use vector instead because vector is inherited from
    _Vector_const_iterator and _Vector_iterator.

    I think it is ok to use these name like _Data and _Proxy because they
    are inaccessible to the client when they are protected in this parent
    class.
     
    Nephi Immortal, Aug 13, 2011
    #6
  7. Nephi Immortal

    Ian Collins Guest

    On 08/13/11 12:32 PM, Nephi Immortal wrote:
    > On Aug 12, 3:27 pm, red floyd<> wrote:
    >>
    >> Any identifier with a leading underscore followed by an upper-case
    >> letter is reserved to the implementation in ANY scope. This means
    >> that you may not use such identifiers (like _Proxy) for your own
    >> purposes.

    >
    > You refer underscore with name is implementation. I think you refer
    > an example -- _Vector_const_iterator and _Vector_iterator. The client
    > can’t use either _Vector_const_iterator or _Vector_iterator. He needs
    > to use vector instead because vector is inherited from
    > _Vector_const_iterator and _Vector_iterator.
    >
    > I think it is ok to use these name like _Data and _Proxy because they
    > are inaccessible to the client when they are protected in this parent
    > class.


    What parts of "reserved to the implementation" and "you may not use"
    weren't clear?

    --
    Ian Collins
     
    Ian Collins, Aug 13, 2011
    #7
  8. Nephi Immortal

    red floyd Guest

    On 8/14/2011 8:47 PM, Paavo Helde wrote:
    > red floyd<> wrote in news:j23f71$9f3$1@dont-
    > email.me:
    >
    >> On 8/12/2011 12:07 AM, Paavo Helde wrote:
    >>> Nephi Immortal<> wrote in

    >>
    >>>> class Object
    >>>> {
    >>>> private:
    >>>> class _Proxy;
    >>>
    >>> Using such a name is UB, so definitely your code has undefined

    > behavior
    >>> ;-)

    >>
    >> Is it UB, or is the code simply ill-formed?

    >
    > From [lib.reserved.names]:
    >
    > "The C + + Standard Library reserves the following kinds of names:
    > [...]
    > — Global names
    > [...]
    > If the program declares or defines a name in a context where it is
    > reserved, other than as explicitly allowed by this clause, the behavior
    > is undefined."


    Thanks, Paavo, I didn't have my copy of the Standard available at the
    time, and I couldn't remember what it said. I just wasn't sure which
    "error" condition it was considered -- UB or ill-formed.

    Much obliged.
     
    red floyd, Aug 15, 2011
    #8
  9. Nephi Immortal

    TJorgenson Guest

    > I think it is ok to use these name like _Data and _Proxy because they
    > are inaccessible to the client when they are protected in this parent
    > class.- Hide quoted text -
    >


    The compiler is allow to create a macro with these names as well.
    Macros can't be scoped.
     
    TJorgenson, Aug 16, 2011
    #9
    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. New Bee

    Tied Up In Knots ASP.NET DataGrid

    New Bee, Sep 6, 2007, in forum: ASP .Net
    Replies:
    0
    Views:
    396
    New Bee
    Sep 6, 2007
  2. Aldorus
    Replies:
    5
    Views:
    5,365
    Aldorus
    Apr 24, 2009
  3. Larry Woods
    Replies:
    5
    Views:
    378
    Mark Schupp
    Jul 13, 2004
  4. Richard Kilmer
    Replies:
    2
    Views:
    121
    tony summerfelt
    Jun 13, 2004
  5. Clint Olsen

    Help with tied/nested data structures

    Clint Olsen, Jul 19, 2006, in forum: Perl Misc
    Replies:
    12
    Views:
    152
    Mumia W.
    Jul 20, 2006
Loading...

Share This Page