API design choice pointer vs. object

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

    #1

    API design choice pointer vs. object

    Hi,
    I am designing an API and the problem that I have is more of a
    design issue. In my API say I have a class A and B, as shown below

    class A{
    public:
    void doSomethingWith B( B * b)
    {
    //do something with b
    //possibly store in a list
    listB.push_back (b);
    }
    private:
    std::vector<B *> listB;
    };

    class B
    {
    ///some declarations and /or data members
    };

    Now the problem is either the interface to doSomethingWith B could be

    void doSomethingWith B( B * b)
    or
    void doSomethingWith B( B & b)

    If I use pointers they come with all the mess as then I might have to
    do some sort of reference counting on them to tell somebody that I am
    storing the pointer to B and possibly call delete or unref on them when
    I remove them from the list if the ref count goes to 0. This adds lots
    of memory management overhead /code to the piece above.

    If I use reference rather then pointers, then probably I am not giving
    the user of the API the full flexibility. I am not very sure that what
    pros /cons will it have if I don't provide a interface with pointers.

    Frankly until now I almost used to use pointers everywhere for member
    objects, for method parameters, method return type. And this I feel is
    bad.

    If people can provide reasons for/against the pointer/reference
    interface then it would help a lot.

    Thanks,
    Divick

  • Victor Bazarov

    #2
    Re: API design choice pointer vs. object

    Divick wrote:[color=blue]
    > [..]
    > If people can provide reasons for/against the pointer/reference
    > interface then it would help a lot.[/color]

    Can you say, "Google"? "Pointer versus reference" discussion is such
    a dead horse that I can barely see the tracks in the dust where the whip
    hit it last time we were beating it.

    V
    --
    Please remove capital As from my address when replying by mail

    Comment

    • Noah Roberts

      #3
      Re: API design choice pointer vs. object


      Divick wrote:[color=blue]
      > Hi,
      > I am designing an API and the problem that I have is more of a
      > design issue. In my API say I have a class A and B, as shown below
      >
      > class A{
      > public:
      > void doSomethingWith B( B * b)
      > {
      > //do something with b
      > //possibly store in a list
      > listB.push_back (b);
      > }
      > private:
      > std::vector<B *> listB;
      > };
      >
      > class B
      > {
      > ///some declarations and /or data members
      > };
      >
      > Now the problem is either the interface to doSomethingWith B could be
      >
      > void doSomethingWith B( B * b)
      > or
      > void doSomethingWith B( B & b)[/color]

      Is B polymorphic? If yes you have your answer, it must be the former.

      Do you want to keep copies of B or the actual B itself? If copies then
      it can be the later but otherwise must be former.

      For reference counting and such if you have the option you should use
      Boost's shared_ptr. If not then create one...it isn't too tough.

      Comment

      • Marcus Kwok

        #4
        Re: API design choice pointer vs. object

        Noah Roberts <roberts.noah@g mail.com> wrote:[color=blue]
        >
        > Divick wrote:[color=green]
        >> Now the problem is either the interface to doSomethingWith B could be
        >>
        >> void doSomethingWith B( B * b)
        >> or
        >> void doSomethingWith B( B & b)[/color]
        >
        > Is B polymorphic? If yes you have your answer, it must be the former.[/color]

        I think polymorphism works with references too:


        #include <iostream>

        class A {
        public:
        virtual ~A() { }
        virtual void do_something() { std::cout << "A::do_somethin g()\n"; }
        };

        class B : public A {
        public:
        virtual void do_something() { std::cout << "B::do_somethin g()\n"; }
        };

        void do_it(A& a)
        {
        a.do_something( );
        }

        int main()
        {
        B b;
        do_it(b);

        return 0;
        }


        Output:
        B::do_something ()


        --
        Marcus Kwok

        Comment

        • Axter

          #5
          Re: API design choice pointer vs. object

          Noah Roberts wrote:[color=blue]
          > Divick wrote:[color=green]
          > > Hi,
          > > I am designing an API and the problem that I have is more of a
          > > design issue. In my API say I have a class A and B, as shown below
          > >
          > > class A{
          > > public:
          > > void doSomethingWith B( B * b)
          > > {
          > > //do something with b
          > > //possibly store in a list
          > > listB.push_back (b);
          > > }
          > > private:
          > > std::vector<B *> listB;
          > > };
          > >
          > > class B
          > > {
          > > ///some declarations and /or data members
          > > };
          > >
          > > Now the problem is either the interface to doSomethingWith B could be
          > >
          > > void doSomethingWith B( B * b)
          > > or
          > > void doSomethingWith B( B & b)[/color]
          >
          > Is B polymorphic? If yes you have your answer, it must be the former.[/color]

          That should not be a factor in making a determiniation.
          If B is polymorphic, it will work with pointers or reference type.


          Author's like Herb Sutter, recommend preferring to use reference type
          over pointer type, because a pointer can mean two things, and therefore
          more ambiguous.

          I recommend a reference type, unless you know for sure you need a
          pointer.

          Comment

          • Mirek Fidler

            #6
            Re: API design choice pointer vs. object

            [color=blue]
            > void doSomethingWith B( B * b)
            > or
            > void doSomethingWith B( B & b)
            >
            > If I use pointers they come with all the mess as then I might have to
            > do some sort of reference counting on them to tell somebody that I am
            > storing the pointer to B and possibly call delete or unref on them when
            > I remove them from the list if the ref count goes to 0. This adds lots
            > of memory management overhead /code to the piece above.
            >
            > If I use reference rather then pointers, then probably I am not giving
            > the user of the API the full flexibility. I am not very sure that what
            > pros /cons will it have if I don't provide a interface with pointers.[/color]

            ....or quite opposite. In fact, when designed right, you can gain much
            more flexibility without pointers and passing ownership (actually, this
            is about ownership rahter than anything else). See

            http://upp.sourceforge .net/www$uppweb$over view$en-us.html

            (I think the "Who owns widgets" section is the most relevant here).

            Mirek

            Comment

            • Daniel T.

              #7
              Re: API design choice pointer vs. object

              In article <1142354650.107 348.261490@i39g 2000cwa.googleg roups.com>,
              "Divick" <divick.kishore @gmail.com> wrote:
              [color=blue]
              > Hi,
              > I am designing an API and the problem that I have is more of a
              > design issue. In my API say I have a class A and B, as shown below
              >
              > class A{
              > public:
              > void doSomethingWith B( B * b)
              > {
              > //do something with b
              > //possibly store in a list
              > listB.push_back (b);
              > }
              > private:
              > std::vector<B *> listB;
              > };
              >
              > class B
              > {
              > ///some declarations and /or data members
              > };
              >
              > Now the problem is either the interface to doSomethingWith B could be
              >
              > void doSomethingWith B( B * b)
              > or
              > void doSomethingWith B( B & b)
              >
              > If people can provide reasons for/against the pointer/reference
              > interface then it would help a lot.[/color]

              In this particular case, because of the possibility of A storing the
              object beyond the return of the function, I would use a pointer.


              --
              Magic depends on tradition and belief. It does not welcome observation,
              nor does it profit by experiment. On the other hand, science is based
              on experience; it is open to correction by observation and experiment.

              Comment

              • Divick

                #8
                Re: API design choice pointer vs. object

                >>..or quite opposite. In fact, when designed right, you can gain much[color=blue][color=green]
                >>more flexibility without pointers and passing ownership (actually, this
                >>is about ownership rahter than anything else). See[/color][/color]
                [color=blue][color=green]
                >>http://upp.sourceforge .net/www$uppweb$over view$en-us.html[/color][/color]
                [color=blue][color=green]
                >>(I think the "Who owns widgets" section is the most relevant here).[/color][/color]
                I did not really get the point that this page is referring to. Could
                you please explain what this page tries to explain.

                Thanks,
                Divick

                Comment

                • Divick

                  #9
                  Re: API design choice pointer vs. object

                  >>In this particular case, because of the possibility of A storing the[color=blue][color=green]
                  >>object beyond the return of the function, I would use a pointer.[/color][/color]
                  What is the reason behind? Could you please elaborate this more.

                  Thanks,
                  Divick

                  Comment

                  • Ben Pope

                    #10
                    Re: API design choice pointer vs. object

                    Divick wrote:[color=blue][color=green][color=darkred]
                    >>> (I think the "Who owns widgets" section is the most relevant
                    >>> here).[/color][/color]
                    >
                    > I did not really get the point that this page is referring to. Could
                    > you please explain what this page tries to explain.[/color]

                    It's probably referring to some lifetime management issues.

                    You should have a clear policy of how objects are allocated and how
                    objects are deleted.

                    If you are pushing "random" pointers into a list, who manages the
                    lifetime of the object to which it points? Is it the list? So that all
                    accesses are done via the list, and if it is removed from the list it is
                    destroyed? Is it some other entity? Will that other enitity remove it
                    from the list?

                    You can use a smart pointer to do the reference counting for you, in
                    which case I suggest boost::shared_p tr.

                    Ben Pope
                    --
                    I'm not just a number. To many, I'm known as a string...

                    Comment

                    • Noah Roberts

                      #11
                      Re: API design choice pointer vs. object


                      Marcus Kwok wrote:[color=blue]
                      > Noah Roberts <roberts.noah@g mail.com> wrote:[color=green]
                      > >
                      > > Divick wrote:[color=darkred]
                      > >> Now the problem is either the interface to doSomethingWith B could be
                      > >>
                      > >> void doSomethingWith B( B * b)
                      > >> or
                      > >> void doSomethingWith B( B & b)[/color]
                      > >
                      > > Is B polymorphic? If yes you have your answer, it must be the former.[/color]
                      >
                      > I think polymorphism works with references too:
                      >
                      >
                      > #include <iostream>
                      >
                      > class A {
                      > public:
                      > virtual ~A() { }
                      > virtual void do_something() { std::cout << "A::do_somethin g()\n"; }
                      > };
                      >
                      > class B : public A {
                      > public:
                      > virtual void do_something() { std::cout << "B::do_somethin g()\n"; }
                      > };
                      >
                      > void do_it(A& a)
                      > {
                      > a.do_something( );
                      > }
                      >
                      > int main()
                      > {
                      > B b;
                      > do_it(b);
                      >
                      > return 0;
                      > }
                      >
                      >
                      > Output:
                      > B::do_something ()[/color]

                      That's nice, now go look at the OP's question again. Both replies to
                      my answer missed an important detail about the OP's code.

                      Comment

                      • Mirek Fidler

                        #12
                        Re: API design choice pointer vs. object

                        Ben Pope wrote:[color=blue]
                        > Divick wrote:
                        >[color=green][color=darkred]
                        >>>> (I think the "Who owns widgets" section is the most relevant
                        >>>> here).[/color]
                        >>
                        >>
                        >> I did not really get the point that this page is referring to. Could
                        >> you please explain what this page tries to explain.[/color]
                        >
                        >
                        > It's probably referring to some lifetime management issues.[/color]

                        Bingo! ;)
                        [color=blue]
                        > You can use a smart pointer to do the reference counting for you, in
                        > which case I suggest boost::shared_p tr.[/color]

                        Or you can design your code so that it does majority of lifetime
                        managemenent by scope destructors.

                        Mirek

                        Comment

                        • Marcus Kwok

                          #13
                          Re: API design choice pointer vs. object

                          >> > Divick wrote:[color=blue][color=green][color=darkred]
                          >> >> Now the problem is either the interface to doSomethingWith B could be
                          >> >>
                          >> >> void doSomethingWith B( B * b)
                          >> >> or
                          >> >> void doSomethingWith B( B & b)[/color][/color][/color]
                          [color=blue][color=green]
                          >> Noah Roberts <roberts.noah@g mail.com> wrote:[color=darkred]
                          >> > Is B polymorphic? If yes you have your answer, it must be the former.[/color][/color][/color]
                          [color=blue]
                          > Marcus Kwok wrote:[color=green]
                          >> I think polymorphism works with references too:[/color][/color]

                          Noah Roberts <roberts.noah@g mail.com> wrote:[color=blue]
                          > That's nice, now go look at the OP's question again. Both replies to
                          > my answer missed an important detail about the OP's code.[/color]

                          OK, I re-read the OP's question, and I'm sorry but I still don't see
                          what this "important detail" is.


                          #include <iostream>
                          #include <vector>

                          class B {
                          public:
                          virtual ~B() { }
                          virtual void blah() { std::cout << "B::blah()\ n"; }
                          };

                          class C : public B {
                          public:
                          virtual void blah() { std::cout << "C::blah()\ n"; }
                          };

                          class A {
                          public:
                          void doSomethingWith B(B* b)
                          {
                          listB.push_back (b);
                          b->blah();
                          }

                          void doSomethingWith B(B& b)
                          {
                          listB.push_back (&b);
                          b.blah();
                          }

                          private:
                          std::vector<B *> listB;
                          };


                          int main()
                          {
                          A a;
                          B b;
                          C c;
                          a.doSomethingWi thB(&b);
                          a.doSomethingWi thB(&c);

                          a.doSomethingWi thB(b);
                          a.doSomethingWi thB(c);
                          }


                          Output:
                          B::blah()
                          C::blah()
                          B::blah()
                          C::blah()

                          --
                          Marcus Kwok

                          Comment

                          • Marcus Kwok

                            #14
                            Re: API design choice pointer vs. object

                            Marcus Kwok <ricecake@gehen nom.net.invalid > wrote:[color=blue]
                            > OK, I re-read the OP's question, and I'm sorry but I still don't see
                            > what this "important detail" is.[/color]

                            Sorry for following up to myself, but upon thinking, maybe you meant the
                            part about storing them in a vector and retaining polymorphic behavior.


                            #include <iostream>
                            #include <vector>

                            class B {
                            public:
                            virtual ~B() { }
                            virtual void blah() { std::cout << "B::blah()\ n"; }
                            };

                            class C : public B {
                            public:
                            virtual void blah() { std::cout << "C::blah()\ n"; }
                            };

                            class A {
                            public:
                            void doSomethingWith B(B* b)
                            {
                            listB.push_back (b);
                            b->blah();
                            }

                            void doSomethingWith B(B& b)
                            {
                            listB.push_back (&b);
                            b.blah();
                            }

                            void doSomethingWith AllB()
                            {
                            std::cout << "ALL:\n";
                            typedef std::vector<B*> ::const_iterato r CI;
                            for (CI i = listB.begin(); i != listB.end(); ++i) {
                            (*i)->blah();
                            }
                            }

                            private:
                            std::vector<B*> listB;
                            };


                            int main()
                            {
                            A a;
                            B b;
                            C c;
                            a.doSomethingWi thB(&b);
                            a.doSomethingWi thB(&c);

                            std::cout << '\n';

                            a.doSomethingWi thB(b);
                            a.doSomethingWi thB(c);

                            std::cout << '\n';

                            a.doSomethingWi thAllB();
                            }


                            Output:
                            B::blah()
                            C::blah()

                            B::blah()
                            C::blah()

                            ALL:
                            B::blah()
                            C::blah()
                            B::blah()
                            C::blah()

                            --
                            Marcus Kwok

                            Comment

                            • Daniel T.

                              #15
                              Re: API design choice pointer vs. object

                              In article <1142529872.510 537.257740@v46g 2000cwv.googleg roups.com>,
                              "Divick" <divick.kishore @gmail.com> wrote:
                              [color=blue][color=green][color=darkred]
                              > >>In this particular case, because of the possibility of A storing the
                              > >>object beyond the return of the function, I would use a pointer.[/color][/color]
                              >
                              > What is the reason behind? Could you please elaborate this more.[/color]

                              1) A holds pointers to B's so it makes sense to accept pointers in the
                              member-function that receives the B's.

                              2) The primary reason references were added to the language was to
                              facilitate operator overloading. In those functions, the object is never
                              stored beyond the end of the function. I tend to follow suit.


                              --
                              Magic depends on tradition and belief. It does not welcome observation,
                              nor does it profit by experiment. On the other hand, science is based
                              on experience; it is open to correction by observation and experiment.

                              Comment

                              Working...