Operatr+ Updated

Discussion in 'C++' started by Nephi Immortal, Feb 19, 2011.

  1. I read the topic – "Error operator+ function” in the previous
    thread. Other folks explained how to put three possible operator+
    functions.
    I wrote two versions of class A and class B. Both classes are
    similar, but one data member of class B uses reference instead of
    value.
    I cannot use class A version. I am told not to use copy constructor
    function. If I do, then copy constructor will have undefined
    behavior. I should always place it in private.
    They said not to put const on any function’s parameter if parameter
    is built-in type such as int. Please clarify why I should not use
    const? Const is necessary to prevent changing parameter and I always
    create temporary local variable and copy const parameter to it.
    Take a look at class A and class B. Compare both of them. Class B
    is ideal to be helper class or proxy class.

    You can write like

    _Low_Byte Low_Byte()
    and
    _High_Byte High_Byte()

    Both functions are in class A.

    You can create two classes: _Low_Byte and _High_Byte. The class B is
    inherited into _Low_Byte class and _High_Byte class. You need to
    redefine operator=.

    I do not need to post two classes since you understood what my code
    means.

    I believe that class A is to be correct code design. What about
    class B?

    class A {
    public:
    explicit A( unsigned int data );
    ~A();
    A( const A &right );
    A &operator=( const A &right );

    A &operator=( unsigned int data );
    operator unsigned int();

    friend A operator+( const A &left, const A &right );
    friend A operator+( const A &left, unsigned int right );
    friend A operator+( unsigned int left, const A &right );

    friend A operator+=( const A &left, const A &right );
    friend A operator+=( const A &left, unsigned int right );
    friend A operator+=( unsigned int left, const A &right );


    private:
    unsigned int m_data;
    };

    A::A( unsigned int data ) : m_data( data ) {
    }

    A::~A() {
    }

    A::A( const A &right ) : m_data( right.m_data ) {
    }

    A &A::eek:perator=( const A &right ) {
    m_data = right.m_data;
    return *this;
    }

    A &A::eek:perator=( unsigned int data ) {
    m_data = data;
    return *this;
    }

    A::eek:perator unsigned int() {
    return m_data;
    }

    A operator+( const A &left, const A &right ) {
    return A( left ) += right;
    }

    A operator+( const A &left, unsigned int right ) {
    return A( left ) += right;
    }

    A operator+( unsigned int left, const A &right ) {
    return left += A( right );
    }

    A operator+=( const A &left, const A &right ) {
    A t( left );
    t.m_data += right.m_data;
    return t;
    }

    A operator+=( const A &left, unsigned int right ) {
    A t( left );
    t.m_data += right;
    return t;
    }

    A operator+=( unsigned int left, const A &right ) {
    A t( right );
    t.m_data += left;
    return t;
    }

    class B {
    public:
    explicit B( unsigned int &data );
    ~B();
    B( const B &right );
    B &operator=( const B &right );

    B &operator=( unsigned int data );
    operator unsigned int();

    friend unsigned int operator+( const B &left, const B &right );
    friend unsigned int operator+( const B &left, unsigned int right );
    friend unsigned int operator+( unsigned int left, const B &right );

    friend unsigned int operator+=( const B &left, const B &right );
    friend unsigned int operator+=( const B &left, unsigned int right );
    friend unsigned int operator+=( unsigned int left, const B &right );


    private:
    unsigned int &m_data;
    };

    B::B( unsigned int &data ) : m_data( data ) {
    }

    B::~B() {
    }

    B::B( const B &right ) : m_data( right.m_data ) {
    }

    B &B::eek:perator=( const B &right ) {
    m_data &= 0xFF00u;
    m_data |= ( right.m_data & 0xFFu );
    return *this;
    }

    B &B::eek:perator=( unsigned int data ) {
    m_data &= 0xFF00u;
    m_data |= ( data & 0xFFu );
    return *this;
    }

    B::eek:perator unsigned int() {
    return m_data & 0xFFu;
    }

    unsigned int operator+( const B &left, const B &right ) {
    unsigned int t = left.m_data;
    t += right.m_data;
    return t;
    }

    unsigned int operator+( const B &left, unsigned int right ) {
    unsigned int t = left.m_data;
    t += right;
    return t;
    }

    unsigned int operator+( unsigned int left, const B &right ) {
    unsigned int t = right.m_data;
    t += left;
    return t;
    }

    unsigned int operator+=( const B &left, const B &right ) {
    unsigned int t = left.m_data;
    t += right.m_data;
    return t;
    }

    unsigned int operator+=( const B &left, unsigned int right ) {
    unsigned int t = left.m_data;
    t += right;
    return t;
    }

    unsigned int operator+=( unsigned int left, const B &right ) {
    unsigned int t = right.m_data;
    t += left;
    return t;
    }


    int main () {
    A a( 2 ), b( 4 ), c( 0 );

    c = a + b;
    c = a + 5u;
    c = 7u + b;

    unsigned int data = 0x1234u, data2 = 0x5678u, data3 = 0xCCCCu;
    B d( data ), e( data2 ), f( data3 );

    f = d + e;
    f = d + 0x10u;
    f = 0x30u + e;

    return 0;
    }
     
    Nephi Immortal, Feb 19, 2011
    #1
    1. Advertising

  2. Nephi Immortal

    Ian Collins Guest

    On 02/20/11 09:04 AM, Nephi Immortal wrote:
    > I read the topic – "Error operator+ function” in the previous
    > thread. Other folks explained how to put three possible operator+
    > functions.
    > I wrote two versions of class A and class B. Both classes are
    > similar, but one data member of class B uses reference instead of
    > value.
    > I cannot use class A version. I am told not to use copy constructor
    > function. If I do, then copy constructor will have undefined
    > behavior. I should always place it in private.


    Told by whom and in what context?

    > They said not to put const on any function’s parameter if parameter
    > is built-in type such as int.Please clarify why I should not use
    > const?


    That's because it doesn't have any meaning for a value parameter (the
    same would apply for any type passed by value).

    > Const is necessary to prevent changing parameter and I always
    > create temporary local variable and copy const parameter to it.


    That only applies if the parameter is a reference or a pointer. Both of
    these refer to objects in the scope of the caller, so declaring the
    parameter const prevents the called function changing the original
    value. Value parameters are copies of the original, Changing them has
    no effect on the the original.

    > Take a look at class A and class B. Compare both of them. Class B
    > is ideal to be helper class or proxy class.
    >
    > You can write like
    >
    > _Low_Byte Low_Byte()
    > and
    > _High_Byte High_Byte()
    >
    > Both functions are in class A.
    >
    > You can create two classes: _Low_Byte and _High_Byte. The class B is
    > inherited into _Low_Byte class and _High_Byte class. You need to
    > redefine operator=.


    This is hard to parse.

    > I do not need to post two classes since you understood what my code
    > means.
    >
    > I believe that class A is to be correct code design. What about
    > class B?
    >
    > class A {
    > public:
    > explicit A( unsigned int data );
    > ~A();
    > A( const A&right );
    > A&operator=( const A&right );
    >
    > A&operator=( unsigned int data );
    > operator unsigned int();
    >
    > friend A operator+( const A&left, const A&right );
    > friend A operator+( const A&left, unsigned int right );
    > friend A operator+( unsigned int left, const A&right );
    >
    > friend A operator+=( const A&left, const A&right );
    > friend A operator+=( const A&left, unsigned int right );
    > friend A operator+=( unsigned int left, const A&right );


    These should be members, returning A&. += updates the current instance,
    it doesn't create a new one.

    >
    > private:
    > unsigned int m_data;
    > };


    <snip>

    > class B {
    > public:
    > explicit B( unsigned int&data );


    Why do you use an int& here?

    I won't comment further, I'm not sure what B is doing.

    --
    Ian Collins
     
    Ian Collins, Feb 19, 2011
    #2
    1. Advertising

  3. On Feb 19, 4:42 pm, Ian Collins <> wrote:
    > On 02/20/11 09:04 AM, Nephi Immortal wrote:
    >
    > >    I read the topic "Error operator+ function in the previous
    > > thread.  Other folks explained how to put three possible operator+
    > > functions.
    > >    I wrote two versions of class A and class B.  Both classes are
    > > similar, but one data member of class B uses reference instead of
    > > value.
    > >    I cannot use class A version.  I am told not to use copy constructor
    > > function.  If I do, then copy constructor will have undefined
    > > behavior.  I should always place it in private.

    >
    > Told by whom and in what context?
    >
    > >    They said not to put const on any function s parameter if parameter
    > > is built-in type such as int.Please clarify why I should not use

    >
    >  > const?
    >
    > That's because it doesn't have any meaning for a value parameter (the
    > same would apply for any type passed by value).
    >
    > > Const is necessary to prevent changing parameter and I always
    > > create temporary local variable and copy const parameter to it.

    >
    > That only applies if the parameter is a reference or a pointer.  Both of
    > these refer to objects in the scope of the caller, so declaring the
    > parameter const prevents the called function changing the original
    > value.  Value parameters are copies of the original, Changing them has
    > no effect on the the original.
    >
    > >    Take a look at class A and class B.  Compare both of them.  Class B
    > > is ideal to be helper class or proxy class.

    >
    > > You can write like

    >
    > > _Low_Byte Low_Byte()
    > > and
    > > _High_Byte High_Byte()

    >
    > > Both functions are in class A.

    >
    > >    You can create two classes: _Low_Byte and _High_Byte.  The class B is
    > > inherited into _Low_Byte class and _High_Byte class.  You need to
    > > redefine operator=.

    >
    > This is hard to parse.
    >
    >
    >
    >
    >
    > >    I do not need to post two classes since you understood what my code
    > > means.

    >
    > >    I believe that class A is to be correct code design.  What about
    > > class B?

    >
    > > class A {
    > > public:
    > >    explicit A( unsigned int data );
    > >    ~A();
    > >    A( const A&right );
    > >    A&operator=( const A&right );

    >
    > >    A&operator=( unsigned int data );
    > >    operator unsigned int();

    >
    > >    friend A operator+( const A&left, const A&right );
    > >    friend A operator+( const A&left, unsigned int right );
    > >    friend A operator+( unsigned int left, const A&right );

    >
    > >    friend A operator+=( const A&left, const A&right );
    > >    friend A operator+=( const A&left, unsigned int right );
    > >    friend A operator+=( unsigned int left, const A&right );

    >
    > These should be members, returning A&.  += updates the current instance,
    > it doesn't create a new one.
    >
    >
    >
    > > private:
    > >    unsigned int m_data;
    > > };

    >
    > <snip>
    >
    > > class B {
    > > public:
    > >    explicit B( unsigned int&data );

    >
    > Why do you use an int& here?
    >
    > I won't comment further, I'm not sure what B is doing.


    I tried to explain above. Class B needs to use reference on
    constructor and data member. I did not post two functions. It should
    clarify clearly.

    Class A {
    ....
    B Low_Byte();
    B High_Byte();
    ....
    };

    B Low_Byte() {
    Return B( this->m_data );
    }

    B High_Byte() {
    Return B( this->m_data );
    }

    Now, you see class B modifies class A’s data member through reference
    when Low_Byte() function is called. It looks like this.

    A a( 2 ), b( 4 ), c( 0 );
    c.Low_Byte() = a.Low_Byte() + b.Low_Byte();

    You notice that class B’s operator+ only returns unsigned int instead
    of returning class B reference. Returning class B reference can cause
    to modify class A’s data member incorrectly through class B’s copy
    constructor since returning class B should be local and not
    reference. Returning unsigned int is the answer and class B’s
    operator=( unsigned int ) is called before reference can modify class
    A’s data member correctly.

    Am I saying clearly?

    Please explain why you think operator+ should be member function. It
    needs to be global function because it has three possible operator+.
    Other folks explained this earlier.
     
    Nephi Immortal, Feb 19, 2011
    #3
  4. Nephi Immortal

    Ian Collins Guest

    On 02/20/11 12:24 PM, Nephi Immortal wrote:
    > On Feb 19, 4:42 pm, Ian Collins<> wrote:
    >> On 02/20/11 09:04 AM, Nephi Immortal wrote:
    >>
    >>> class A {
    >>> public:
    >>> explicit A( unsigned int data );
    >>> ~A();
    >>> A( const A&right );
    >>> A&operator=( const A&right );

    >>
    >>> A&operator=( unsigned int data );
    >>> operator unsigned int();

    >>
    >>> friend A operator+( const A&left, const A&right );
    >>> friend A operator+( const A&left, unsigned int right );
    >>> friend A operator+( unsigned int left, const A&right );

    >>
    >>> friend A operator+=( const A&left, const A&right );
    >>> friend A operator+=( const A&left, unsigned int right );
    >>> friend A operator+=( unsigned int left, const A&right );

    >>
    >> These should be members, returning A&. += updates the current instance,
    >> it doesn't create a new one.

    >
    >>> private:
    >>> unsigned int m_data;
    >>> };

    >>
    >> <snip>
    >>
    >>> class B {
    >>> public:
    >>> explicit B( unsigned int&data );

    >>
    >> Why do you use an int& here?
    >>
    >> I won't comment further, I'm not sure what B is doing.

    >
    > I tried to explain above. Class B needs to use reference on
    > constructor and data member. I did not post two functions. It should
    > clarify clearly.
    >
    > Class A {
    > ....
    > B Low_Byte();
    > B High_Byte();
    > ....
    > };
    >
    > B Low_Byte() {
    > Return B( this->m_data );
    > }
    >
    > B High_Byte() {
    > Return B( this->m_data );
    > }
    >
    > Now, you see class B modifies class A’s data member through reference
    > when Low_Byte() function is called. It looks like this.
    >
    > A a( 2 ), b( 4 ), c( 0 );
    > c.Low_Byte() = a.Low_Byte() + b.Low_Byte();
    >
    > You notice that class B’s operator+ only returns unsigned int instead
    > of returning class B reference. Returning class B reference can cause
    > to modify class A’s data member incorrectly through class B’s copy
    > constructor since returning class B should be local and not
    > reference. Returning unsigned int is the answer and class B’s
    > operator=( unsigned int ) is called before reference can modify class
    > A’s data member correctly.
    >
    > Am I saying clearly?


    Yes, that makes more sense.

    > Please explain why you think operator+ should be member function. It
    > needs to be global function because it has three possible operator+.
    > Other folks explained this earlier.


    I didn't say that, I said operator += should be a member. Please
    comment in-line, it makes replying with relevant context easier.

    --
    Ian Collins
     
    Ian Collins, Feb 19, 2011
    #4
  5. Nephi Immortal

    James Kanze Guest

    On Feb 19, 8:04 pm, Nephi Immortal <> wrote:
    > I read the topic – "Error operator+ function” in the previous
    > thread. Other folks explained how to put three possible operator+
    > functions.
    > I wrote two versions of class A and class B. Both classes are
    > similar, but one data member of class B uses reference instead of
    > value.
    > I cannot use class A version. I am told not to use copy constructor
    > function. If I do, then copy constructor will have undefined
    > behavior. I should always place it in private.
    > They said not to put const on any function’s parameter if parameter
    > is built-in type such as int. Please clarify why I should not use
    > const? Const is necessary to prevent changing parameter and I always
    > create temporary local variable and copy const parameter to it.
    > Take a look at class A and class B. Compare both of them. Class B
    > is ideal to be helper class or proxy class.


    > You can write like


    > _Low_Byte Low_Byte()
    > and
    > _High_Byte High_Byte()


    > Both functions are in class A.


    > You can create two classes: _Low_Byte and _High_Byte. The class B is
    > inherited into _Low_Byte class and _High_Byte class. You need to
    > redefine operator=.


    > I do not need to post two classes since you understood what my code
    > means.


    > I believe that class A is to be correct code design. What about
    > class B?


    > class A {
    > public:
    > explicit A( unsigned int data );
    > ~A();
    > A( const A &right );
    > A &operator=( const A &right );


    > A &operator=( unsigned int data );
    > operator unsigned int();


    This looks like an excellent decision: making the conversion
    constructor explicit, then overriding operator=. On the other
    hand, I'm just slightly sceptical about one thing: most of the
    time when you implement a class, you want it's operators, and
    not those of the built-in type, whenever the class is used. The
    presence of a user defined conversion operator means that you
    risk getting just the opposite. User defined conversion
    operators tend to be very dangerous. (I believe C++0x allows
    them to be declared explicit. This would alleviate most of the
    danger.)

    > friend A operator+( const A &left, const A &right );
    > friend A operator+( const A &left, unsigned int right );
    > friend A operator+( unsigned int left, const A &right );


    Just a nit, but if the operators aren't defined inline, why make
    them friend?

    > friend A operator+=( const A &left, const A &right );
    > friend A operator+=( const A &left, unsigned int right );
    > friend A operator+=( unsigned int left, const A &right );


    The usual convention is for the first to to be members, not
    friends (although IMHO, there is a good argument for making them
    non-members, but with a non-const left parameter). As for the
    last, it's probably irrelevant, since the it is covered by the
    builtin operator += and the conversion operator.

    At any rate, += should modify it's left arguement, so passing it
    a reference to const is out.

    > private:
    > unsigned int m_data;
    > };


    > A::A( unsigned int data ) : m_data( data ) {
    > }


    > A::~A() {
    > }


    > A::A( const A &right ) : m_data( right.m_data ) {
    > }


    > A &A::eek:perator=( const A &right ) {
    > m_data = right.m_data;
    > return *this;
    > }


    Given the definition of the last three, I'd just let the
    compiler take care of them (with perhaps a comment saying that
    the compiler provided defaults are used).

    > A &A::eek:perator=( unsigned int data ) {
    > m_data = data;
    > return *this;
    > }


    > A::eek:perator unsigned int() {
    > return m_data;
    > }


    > A operator+( const A &left, const A &right ) {
    > return A( left ) += right;
    > }


    > A operator+( const A &left, unsigned int right ) {
    > return A( left ) += right;
    > }


    > A operator+( unsigned int left, const A &right ) {
    > return left += A( right );
    > }


    Given these definitions, why friend?

    > A operator+=( const A &left, const A &right ) {
    > A t( left );
    > t.m_data += right.m_data;
    > return t;
    > }


    This is very dubious. A += operator which doesn't modify the
    left argument? I'd call this operator overloading abuse, and
    very, very poor design.

    > A operator+=( const A &left, unsigned int right ) {
    > A t( left );
    > t.m_data += right;
    > return t;
    > }


    > A operator+=( unsigned int left, const A &right ) {
    > A t( right );
    > t.m_data += left;
    > return t;
    > }


    > class B {
    > public:
    > explicit B( unsigned int &data );
    > ~B();
    > B( const B &right );
    > B &operator=( const B &right );


    > B &operator=( unsigned int data );
    > operator unsigned int();


    > friend unsigned int operator+( const B &left, const B &right );
    > friend unsigned int operator+( const B &left, unsigned int right );
    > friend unsigned int operator+( unsigned int left, const B &right );


    > friend unsigned int operator+=( const B &left, const B &right );
    > friend unsigned int operator+=( const B &left, unsigned int right );
    > friend unsigned int operator+=( unsigned int left, const B &right );


    > private:
    > unsigned int &m_data;


    It's almost always an error to have a reference as a data
    member. And I can't think of a single exception when the class
    has value semantics, as is the case here. Value semantics imply
    both copy and assignment, and that both have roughly the same
    semantics. Which isn't possible with reference members.

    > };


    > B::B( unsigned int &data ) : m_data( data ) {
    > }
    >
    > B::~B() {
    > }
    >
    > B::B( const B &right ) : m_data( right.m_data ) {
    > }


    > B &B::eek:perator=( const B &right ) {
    > m_data &= 0xFF00u;
    > m_data |= ( right.m_data & 0xFFu );
    > return *this;
    > }


    Note that this could have very undesirable semantics because of
    the reference member. You could end up modifying the value of
    right.

    --
    James Kanze
     
    James Kanze, Feb 20, 2011
    #5
  6. Nephi Immortal

    James Kanze Guest

    On Feb 19, 10:42 pm, Ian Collins <> wrote:
    > On 02/20/11 09:04 AM, Nephi Immortal wrote:


    > > friend A operator+=( const A&left, const A&right );
    > > friend A operator+=( const A&left, unsigned int right );
    > > friend A operator+=( unsigned int left, const A&right );


    > These should be members, returning A&. += updates the current instance,
    > it doesn't create a new one.


    That they should be members is the conventional approach. One
    could argue that they should be non-members, taking an A& (no
    const) as argument: the built-in += requires an lvalue as left
    argument; the only way to simulate this is to have a non-member
    taking a reference to non-const.

    On the other hand, I always make them members too. Given the
    ubiquity of the idiom, it's best to go along with it, rather
    than cause the reader to ask all sorts of questions.

    --
    James Kanze
     
    James Kanze, Feb 20, 2011
    #6
  7. On Feb 20, 8:17 am, James Kanze <> wrote:
    > On Feb 19, 8:04 pm, Nephi Immortal <> wrote:
    >
    >
    >
    >
    >
    > >         I read the topic – "Error operator+ function” in the previous
    > > thread.  Other folks explained how to put three possible operator+
    > > functions.
    > >         I wrote two versions of class A and class B.  Both classes are
    > > similar, but one data member of class B uses reference instead of
    > > value.
    > >         I cannot use class A version.  I am told not to use copy constructor
    > > function.  If I do, then copy constructor will have undefined
    > > behavior.  I should always place it in private.
    > >         They said not to put const on any function’s parameter if parameter
    > > is built-in type such as int.  Please clarify why I should not use
    > > const?  Const is necessary to prevent changing parameter and I always
    > > create temporary local variable and copy const parameter to it.
    > >         Take a look at class A and class B.  Compare both of them.  Class B
    > > is ideal to be helper class or proxy class.
    > > You can write like
    > > _Low_Byte Low_Byte()
    > > and
    > > _High_Byte High_Byte()
    > > Both functions are in class A.
    > >         You can create two classes: _Low_Byte and _High_Byte.  The class B is
    > > inherited into _Low_Byte class and _High_Byte class.  You need to
    > > redefine operator=.
    > >         I do not need to post two classes since you understood what my code
    > > means.
    > >         I believe that class A is to be correct code design.  What about
    > > class B?
    > > class A {
    > > public:
    > >         explicit A( unsigned int data );
    > >         ~A();
    > >         A( const A &right );
    > >         A &operator=( const A &right );
    > >         A &operator=( unsigned int data );
    > >         operator unsigned int();

    >
    > This looks like an excellent decision: making the conversion
    > constructor explicit, then overriding operator=.  On the other
    > hand, I'm just slightly sceptical about one thing: most of the
    > time when you implement a class, you want it's operators, and
    > not those of the built-in type, whenever the class is used.  The
    > presence of a user defined conversion operator means that you
    > risk getting just the opposite.  User defined conversion
    > operators tend to be very dangerous.  (I believe C++0x allows
    > them to be declared explicit.  This would alleviate most of the
    > danger.)
    >
    > >         friend A operator+( const A &left, const A &right );
    > >         friend A operator+( const A &left, unsigned int right );
    > >         friend A operator+( unsigned int left, const A &right );

    >
    > Just a nit, but if the operators aren't defined inline, why make
    > them friend?
    >
    > >         friend A operator+=( const A &left, const A &right );
    > >         friend A operator+=( const A &left, unsigned int right );
    > >         friend A operator+=( unsigned int left, const A &right );

    >
    > The usual convention is for the first to to be members, not
    > friends (although IMHO, there is a good argument for making them
    > non-members, but with a non-const left parameter).  As for the
    > last, it's probably irrelevant, since the it is covered by the
    > builtin operator += and the conversion operator.
    >
    > At any rate, += should modify it's left arguement, so passing it
    > a reference to const is out.
    >
    > > private:
    > >         unsigned int m_data;
    > > };
    > > A::A( unsigned int data ) : m_data( data ) {
    > > }
    > > A::~A() {
    > > }
    > > A::A( const A &right ) : m_data( right.m_data ) {
    > > }
    > > A &A::eek:perator=( const A &right ) {
    > >         m_data = right.m_data;
    > >         return *this;
    > > }

    >
    > Given the definition of the last three, I'd just let the
    > compiler take care of them (with perhaps a comment saying that
    > the compiler provided defaults are used).
    >
    >
    >
    >
    >
    > > A &A::eek:perator=( unsigned int data ) {
    > >         m_data = data;
    > >         return *this;
    > > }
    > > A::eek:perator unsigned int() {
    > >         return m_data;
    > > }
    > > A operator+( const A &left, const A &right ) {
    > >         return A( left ) += right;
    > > }
    > > A operator+( const A &left, unsigned int right ) {
    > >         return A( left ) += right;
    > > }
    > > A operator+( unsigned int left, const A &right ) {
    > >         return left += A( right );
    > > }

    >
    > Given these definitions, why friend?
    >
    > > A operator+=( const A &left, const A &right ) {
    > >         A t( left );
    > >         t.m_data += right.m_data;
    > >         return t;
    > > }

    >
    > This is very dubious.  A += operator which doesn't modify the
    > left argument?  I'd call this operator overloading abuse, and
    > very, very poor design.
    >
    >
    >
    >
    >
    > > A operator+=( const A &left, unsigned int right ) {
    > >         A t( left );
    > >         t.m_data += right;
    > >         return t;
    > > }
    > > A operator+=( unsigned int left, const A &right ) {
    > >         A t( right );
    > >         t.m_data += left;
    > >         return t;
    > > }
    > > class B {
    > > public:
    > >         explicit B( unsigned int &data );
    > >         ~B();
    > >         B( const B &right );
    > >         B &operator=( const B &right );
    > >         B &operator=( unsigned int data );
    > >         operator unsigned int();
    > >         friend unsigned int operator+( const B &left, const B &right );
    > >         friend unsigned int operator+( const B &left, unsigned int right );
    > >         friend unsigned int operator+( unsigned int left, const B &right );
    > >         friend unsigned int operator+=( const B &left, const B &right );
    > >         friend unsigned int  operator+=( const B &left, unsigned int right );
    > >         friend unsigned int  operator+=( unsigned int left, const B &right );
    > > private:
    > >         unsigned int &m_data;

    >
    > It's almost always an error to have a reference as a data
    > member.  And I can't think of a single exception when the class
    > has value semantics, as is the case here.  Value semantics imply
    > both copy and assignment, and that both have roughly the same
    > semantics.  Which isn't possible with reference members.
    >
    > > };
    > > B::B( unsigned int &data ) : m_data( data ) {
    > > }

    >
    > > B::~B() {
    > > }

    >
    > > B::B( const B &right ) : m_data( right.m_data ) {
    > > }
    > > B &B::eek:perator=( const B &right ) {
    > >         m_data &= 0xFF00u;
    > >         m_data |= ( right.m_data & 0xFFu );
    > >         return *this;
    > > }

    >
    > Note that this could have very undesirable semantics because of
    > the reference member.  You could end up modifying the value of
    > right.



    James,

    Please review previous thread at
    http://groups.google.com/group/comp...?hl=en&lnk=gst&q=Paul Bibbings ImmortalNephi#..
    Paul Bibbings talked about proxy class and operator cast returns
    reference. I posted RGB Array class eight months ago. It is very
    similar what I am talking about operator+ here.
    Byte class is the similar to class B that takes constructor and data
    member by reference. He said not to use copy constructor if proxy
    class is used or it will have undefined behavior.
    I am confused when you said. This code is abused if proxy class is
    used.

    Nephi


    > --
    > James Kanze- Hide quoted text -
    >
    > - Show quoted text -- Hide quoted text -
    >
    > - Show quoted text -- Hide quoted text -
    >
    > - Show quoted text -
     
    Nephi Immortal, Feb 20, 2011
    #7
  8. Nephi Immortal

    James Kanze Guest

    On Feb 20, 4:12 pm, Nephi Immortal <> wrote:
    > On Feb 20, 8:17 am, James Kanze <> wrote:


    [...]
    > > > class B {
    > > > public:
    > > > explicit B( unsigned int &data );
    > > > ~B();
    > > > B( const B &right );
    > > > B &operator=( const B &right );
    > > > B &operator=( unsigned int data );
    > > > operator unsigned int();
    > > > friend unsigned int operator+( const B &left, const B &right );
    > > > friend unsigned int operator+( const B &left, unsigned int right );
    > > > friend unsigned int operator+( unsigned int left, const B &right );
    > > > friend unsigned int operator+=( const B &left, const B &right );
    > > > friend unsigned int operator+=( const B &left, unsigned int right );
    > > > friend unsigned int operator+=( unsigned int left, const B &right );
    > > > private:
    > > > unsigned int &m_data;


    > > It's almost always an error to have a reference as a data
    > > member. And I can't think of a single exception when the class
    > > has value semantics, as is the case here. Value semantics imply
    > > both copy and assignment, and that both have roughly the same
    > > semantics. Which isn't possible with reference members.


    > > > };
    > > > B::B( unsigned int &data ) : m_data( data ) {
    > > > }


    > > > B::~B() {
    > > > }


    > > > B::B( const B &right ) : m_data( right.m_data ) {
    > > > }
    > > > B &B::eek:perator=( const B &right ) {
    > > > m_data &= 0xFF00u;
    > > > m_data |= ( right.m_data & 0xFFu );
    > > > return *this;
    > > > }


    > > Note that this could have very undesirable semantics because of
    > > the reference member. You could end up modifying the value of
    > > right.


    > Please review previous thread athttp://groups.google.com/group/comp.lang.c++/browse_thread/thread/5c5....


    It's really too long for me to study it in detail, however...

    > Paul Bibbings talked about proxy class and operator cast returns
    > reference. I posted RGB Array class eight months ago. It is very
    > similar what I am talking about operator+ here.
    > Byte class is the similar to class B that takes constructor and data
    > member by reference. He said not to use copy constructor if proxy
    > class is used or it will have undefined behavior.
    > I am confused when you said. This code is abused if proxy class is
    > used.


    It's not clear to me here what is a proxy for what, but
    generally, when proxies are used, the proxy class will contain
    a pointer, and not a reference. (And proxy classes don't always
    support operator=, although mine usually do.)

    --
    James Kanze
     
    James Kanze, Feb 21, 2011
    #8
    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. Richard Grimes

    ANN: Fusion workshop updated to .NET 2.0

    Richard Grimes, Nov 19, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    440
    Terry Cai
    Dec 6, 2005
  2. Kelly

    dynamic controls not updated

    Kelly, Jun 25, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    893
    Natty Gur
    Jun 25, 2003
  3. Natty Gur

    Re: dynamic controls not updated

    Natty Gur, Jun 25, 2003, in forum: ASP .Net
    Replies:
    3
    Views:
    1,772
    Kelly Lim
    Jun 26, 2003
  4. Bill Priess
    Replies:
    0
    Views:
    438
    Bill Priess
    Aug 5, 2003
  5. Dmitry Korolyov

    Datagrid not updated during delete, but updated during insert and update

    Dmitry Korolyov, Sep 22, 2003, in forum: ASP .Net Datagrid Control
    Replies:
    0
    Views:
    445
    Dmitry Korolyov
    Sep 22, 2003
Loading...

Share This Page