Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Two nested classes are tied together.

Reply
Thread Tools

Two nested classes are tied together.

 
 
Nephi Immortal
Guest
Posts: n/a
 
      08-11-2011
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;
}
 
Reply With Quote
 
 
 
 
red floyd
Guest
Posts: n/a
 
      08-12-2011
On 8/12/2011 12:07 AM, Paavo Helde wrote:
> Nephi Immortal<(E-Mail Removed)> 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?
 
Reply With Quote
 
 
 
 
Nephi Immortal
Guest
Posts: n/a
 
      08-12-2011
On Aug 12, 2:07*am, Paavo Helde <(E-Mail Removed)> wrote:
> Nephi Immortal <(E-Mail Removed)> wrote innews:(E-Mail Removed):
>
>
>
>
>
> > * * *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.
 
Reply With Quote
 
red floyd
Guest
Posts: n/a
 
      08-12-2011
On 8/12/2011 12:16 PM, Nephi Immortal wrote:
> On Aug 12, 2:07 am, Paavo Helde<(E-Mail Removed)> wrote:
>> Nephi Immortal<(E-Mail Removed)> wrote innews:(E-Mail Removed):


>>> 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.


 
Reply With Quote
 
Nephi Immortal
Guest
Posts: n/a
 
      08-13-2011
On Aug 12, 3:27*pm, red floyd <(E-Mail Removed)> wrote:
> On 8/12/2011 12:16 PM, Nephi Immortal wrote:
>
>
>
>
>
> > On Aug 12, 2:07 am, Paavo Helde<(E-Mail Removed)> *wrote:
> >> Nephi Immortal<(E-Mail Removed)> *wrote innews:(E-Mail Removed):
> >>> 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.
 
Reply With Quote
 
Nephi Immortal
Guest
Posts: n/a
 
      08-13-2011
On Aug 12, 3:27*pm, red floyd <(E-Mail Removed)> wrote:
> On 8/12/2011 12:16 PM, Nephi Immortal wrote:
>
>
>
>
>
> > On Aug 12, 2:07 am, Paavo Helde<(E-Mail Removed)> *wrote:
> >> Nephi Immortal<(E-Mail Removed)> *wrote innews:(E-Mail Removed):
> >>> 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.
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      08-13-2011
On 08/13/11 12:32 PM, Nephi Immortal wrote:
> On Aug 12, 3:27 pm, red floyd<(E-Mail Removed)> 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
 
Reply With Quote
 
red floyd
Guest
Posts: n/a
 
      08-15-2011
On 8/14/2011 8:47 PM, Paavo Helde wrote:
> red floyd<(E-Mail Removed)> wrote in news:j23f71$9f3$1@dont-
> email.me:
>
>> On 8/12/2011 12:07 AM, Paavo Helde wrote:
>>> Nephi Immortal<(E-Mail Removed)> 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.




 
Reply With Quote
 
TJorgenson
Guest
Posts: n/a
 
      08-16-2011
> 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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Help with tied/nested data structures Clint Olsen Perl Misc 12 07-20-2006 11:23 AM
Nested Vector Nester Classes are Nested in my Brain Chad E. Dollins C++ 3 11-08-2005 04:46 AM
Nested classes within other classes Tony Johansson C++ 2 12-14-2004 11:41 AM
Nested Classes vs Top-Level Classes kelvSYC Java 2 08-18-2004 07:09 AM
What is the difference between nested classes and inner classes ? Razvan Java 5 07-27-2004 07:59 PM



Advertisments