Members or not

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Marcin Kalicinski

    Members or not

    Hi all,

    What is the best practice with redefining operators for a class:

    namespace Math
    {

    class Matrix
    {
    // ...
    bool operator ==(const Matrix &) const; // (1)
    }

    bool operator ==(const Matrix &, const Matrix &); // (2)
    }

    Should (1) or (2) be preferred? All data members of Matrix are public, so
    there's no problem of access.

    In my program I have more "concrete" mathematical classes like Matrix, and I
    want to define operators like ==, +, - etc. consistently for all of them.
    Which way should I do it best?

    Marcin



  • John Harrison

    #2
    Re: Members or not


    "Marcin Kalicinski" <kalita@poczta. onet.pl> wrote in message
    news:casbci$gq5 $1@korweta.task .gda.pl...[color=blue]
    > Hi all,
    >
    > What is the best practice with redefining operators for a class:
    >
    > namespace Math
    > {
    >
    > class Matrix
    > {
    > // ...
    > bool operator ==(const Matrix &) const; // (1)
    > }
    >
    > bool operator ==(const Matrix &, const Matrix &); // (2)
    > }
    >
    > Should (1) or (2) be preferred? All data members of Matrix are public, so
    > there's no problem of access.
    >[/color]

    For an equality operator 2 should be prefered.

    Here's why, this compiles

    struct X
    {
    X(int);
    };

    extern bool operator==(cons t X&, const X&); // version 2

    int main()
    {
    X x;
    if (1 == x)
    ;
    if (x == 1)
    ;
    }

    but this doesn't

    struct X
    {
    X(int);
    bool operator==(cons t X&) const; // version 1
    };


    int main()
    {
    X x;
    if (1 == x) // error here
    ;
    if (x == 1)
    ;
    }

    By using a member function instead of a free function you impose different
    rules on the conversions that can happen for the first and second
    parameters. C++ will not construct a teemporary X from an int in the case
    commented 'error here' but will do for every other case. Obviously this
    assymetry is a bad idea for something like equality.
    [color=blue]
    > In my program I have more "concrete" mathematical classes like Matrix, and[/color]
    I[color=blue]
    > want to define operators like ==, +, - etc. consistently for all of them.
    > Which way should I do it best?
    >[/color]

    Usually only assignment operators, =, +=, *= etc are defined as members.

    john


    Comment

    • Ron Samuel Klatchko

      #3
      Re: Members or not

      "Marcin Kalicinski" <kalita@poczta. onet.pl> wrote in message news:<casbci$gq 5$1@korweta.tas k.gda.pl>...[color=blue]
      > Hi all,
      >
      > What is the best practice with redefining operators for a class:
      >
      > namespace Math
      > {
      >
      > class Matrix
      > {
      > // ...
      > bool operator ==(const Matrix &) const; // (1)
      > }
      >
      > bool operator ==(const Matrix &, const Matrix &); // (2)
      > }
      >
      > Should (1) or (2) be preferred? All data members of Matrix are public, so
      > there's no problem of access.[/color]

      One limitation of #2 is that the lhs must be a matrix. If you had a
      constructor that took a SomeOtherMatrix class and you had the following
      code.

      Matrix m;
      SomeOtherMatrix sm;

      if (m == sm) // (a)
      if (sm == m) // (b)

      Both (a) and (b) will work with (2) but only (a) will work with (1).

      That said, using public data members isn't very good style. You can either
      make the operator== a friend or you can just use the operator== as a
      forwarding function:

      class Matrix
      {
      ...
      bool equal(const Matrix &other) const;
      ...
      };

      inline bool operator==(cons t Matrix &m1, const Matrix &m2)
      {
      return m1.eq(m2);
      }

      samuel

      Comment

      • Ioannis Vranos

        #4
        Re: Members or not

        Marcin Kalicinski wrote:
        [color=blue]
        > Hi all,
        >
        > What is the best practice with redefining operators for a class:
        >
        > namespace Math
        > {
        >
        > class Matrix
        > {
        > // ...
        > bool operator ==(const Matrix &) const; // (1)
        > }
        >
        > bool operator ==(const Matrix &, const Matrix &); // (2)
        > }
        >
        > Should (1) or (2) be preferred? All data members of Matrix are public, so
        > there's no problem of access.
        >
        > In my program I have more "concrete" mathematical classes like Matrix, and I
        > want to define operators like ==, +, - etc. consistently for all of them.
        > Which way should I do it best?
        >
        > Marcin[/color]



        A good approach used by many is two use the two operand definition (your
        (2)) for objects of different types, while for objects of the same type
        to use the one operand definition inside the class.






        Best regards,

        Ioannis Vranos

        Comment

        • Marcin Kalicinski

          #5
          Re: Members or not


          U¿ytkownik "John Harrison" <john_andronicu s@hotmail.com> napisa³ w
          wiadomo¶ci news:2jdqcfF10b 93fU1@uni-berlin.de...[color=blue]
          >
          > "Marcin Kalicinski" <kalita@poczta. onet.pl> wrote in message
          > news:casbci$gq5 $1@korweta.task .gda.pl...[color=green]
          > > Hi all,
          > >
          > > What is the best practice with redefining operators for a class:
          > >
          > > namespace Math
          > > {
          > >
          > > class Matrix
          > > {
          > > // ...
          > > bool operator ==(const Matrix &) const; // (1)
          > > }
          > >
          > > bool operator ==(const Matrix &, const Matrix &); // (2)
          > > }
          > >
          > > Should (1) or (2) be preferred? All data members of Matrix are public,[/color][/color]
          so[color=blue][color=green]
          > > there's no problem of access.
          > >[/color]
          >
          > For an equality operator 2 should be prefered.
          >
          > Here's why, this compiles
          >
          > struct X
          > {
          > X(int);
          > };
          >
          > extern bool operator==(cons t X&, const X&); // version 2
          >
          > int main()
          > {
          > X x;
          > if (1 == x)
          > ;
          > if (x == 1)
          > ;
          > }
          >
          > but this doesn't
          >
          > struct X
          > {
          > X(int);
          > bool operator==(cons t X&) const; // version 1
          > };
          >
          >
          > int main()
          > {
          > X x;
          > if (1 == x) // error here
          > ;
          > if (x == 1)
          > ;
          > }
          >
          > By using a member function instead of a free function you impose different
          > rules on the conversions that can happen for the first and second
          > parameters. C++ will not construct a teemporary X from an int in the case
          > commented 'error here' but will do for every other case. Obviously this
          > assymetry is a bad idea for something like equality.
          >[color=green]
          > > In my program I have more "concrete" mathematical classes like Matrix,[/color][/color]
          and[color=blue]
          > I[color=green]
          > > want to define operators like ==, +, - etc. consistently for all of[/color][/color]
          them.[color=blue][color=green]
          > > Which way should I do it best?
          > >[/color]
          >
          > Usually only assignment operators, =, +=, *= etc are defined as members.[/color]

          I know that operator = must be a member, but operators +=, *= etc. do not
          have to be. Is there any rationale on making them members anyway?

          Marcin


          Comment

          • John Harrison

            #6
            Re: Members or not

            > >[color=blue][color=green]
            > > Usually only assignment operators, =, +=, *= etc are defined as members.[/color]
            >
            > I know that operator = must be a member, but operators +=, *= etc. do not
            > have to be. Is there any rationale on making them members anyway?
            >[/color]

            I can't think of any reason why making operator+= global would not work, but
            since operator+= operates on a single object it makes sense to me to have it
            as a member function.

            john


            Comment

            • Ioannis Vranos

              #7
              Re: Members or not

              John Harrison wrote:[color=blue][color=green][color=darkred]
              >>>Usually only assignment operators, =, +=, *= etc are defined as members.[/color]
              >>
              >>I know that operator = must be a member, but operators +=, *= etc. do not
              >>have to be. Is there any rationale on making them members anyway?
              >>[/color]
              >
              >
              > I can't think of any reason why making operator+= global would not work, but
              > since operator+= operates on a single object it makes sense to me to have it
              > as a member function.
              >
              > john
              >
              >[/color]


              As I have told in another message, a good approach is to use the two
              operand definition for objects of different types, while for objects of
              the same type to use the one operand definition inside the class.


              For example if we have our type Something to interact with some other
              type, we will use the two operand operator definition.

              If we want to define operators for objects of the same type we will use
              the one operand definitions.

              So if we want our class to interact with some other type with +=, we
              will use the two operand definition (outside of the class), while for an
              operator+= for interaction between objects of our class, we will use the
              one operand definition (inside our class).


              A more specific example is if we want to define an operator<< among
              ostream (cout) and our class Sometype, we will provide a two operand
              definition. The same applies for operator>> between istream (cin) and
              our type, we will define a two operand definition outside our class.


              This also helps maintainability and extensibility.






              Regards,

              Ioannis Vranos

              Comment

              Working...