Implementation of abstract classes

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

    #1

    Implementation of abstract classes

    Hi folks.

    I have some classes which are derived from some base:

    class base {
    void foo();
    void bar();
    };

    class a : public base {
    };

    class b: public base{
    };

    The problem is as follows:

    1) I would like to prevent users from making instances of
    class base
    2) There are no overloaded functions beween the base class
    and the derived classes, so I can not use the usual

    virtual void overloaded_func tion() = 0;

    in the base class.

    As far as I can see, there are two ways to proceed:

    1) make some virtual dummy function that the
    derived classes need to implement
    2) Hide the constructor of base as protected.

    From a semantic point of view the latter solution
    seems the more elegant. Is this a good solution
    or are there traps or snags associated with it?

    Rune
  • Christian Hackl

    #2
    Re: Implementation of abstract classes

    Rune Allnor wrote:
    1) I would like to prevent users from making instances of
    class base
    2) There are no overloaded functions beween the base class
    and the derived classes, so I can not use the usual
    >
    virtual void overloaded_func tion() = 0;
    >
    in the base class.
    If your base class is going to be used polymorphically , you must declare
    its destructor virtual anyway, so you don't need a "dummy" pure virtual
    function. Just declare the destructor itself pure virtual:

    virtual ~base() = 0


    --
    Christian Hackl

    Comment

    • Christian Hackl

      #3
      Re: Implementation of abstract classes

      Rune Allnor wrote:
      1) I would like to prevent users from making instances of
      class base
      2) There are no overloaded functions beween the base class
      and the derived classes, so I can not use the usual
      >
      virtual void overloaded_func tion() = 0;
      >
      in the base class.
      >
      As far as I can see, there are two ways to proceed:
      >
      1) make some virtual dummy function that the
      derived classes need to implement
      2) Hide the constructor of base as protected.
      If your base class is going to be used polymorphically , you must declare
      its destructor virtual anyway, so you don't need a "dummy" pure virtual
      function. Just declare the destructor itself pure virtual:

      virtual ~base() = 0


      --
      Christian Hackl

      Comment

      • Rune Allnor

        #4
        Re: Implementation of abstract classes

        On 20 Sep, 18:40, Christian Hackl <ha...@sbox.tug raz.atwrote:
        Rune Allnor wrote:
        1) I would like to prevent users from making instances of
           class base
        2) There are no overloaded functions beween the base class
           and the derived classes, so I can not use the usual
        >
           virtual void overloaded_func tion() = 0;
        >
           in the base class.
        >
        As far as I can see, there are two ways to proceed:
        >
        1) make some virtual dummy function that the
           derived classes need to implement
        2) Hide the constructor of base as protected.
        >
        If your base class is going to be used polymorphically , you must declare
        its destructor virtual anyway, so you don't need a "dummy" pure virtual
        function. Just declare the destructor itself pure virtual:
        >
        virtual ~base() = 0
        Of course!

        This solution takes care of the case I'm working on
        right now, but how would one do this if there were
        some cleaning up to do on the base class level?

        With the above solution one would have to call some
        base::cleanup() function in each of the derived
        destructors, right?

        Rune

        Comment

        • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

          #5
          Re: Implementation of abstract classes

          On 2008-09-20 18:52, Rune Allnor wrote:
          On 20 Sep, 18:40, Christian Hackl <ha...@sbox.tug raz.atwrote:
          >Rune Allnor wrote:
          1) I would like to prevent users from making instances of
          class base
          2) There are no overloaded functions beween the base class
          and the derived classes, so I can not use the usual
          >>
          virtual void overloaded_func tion() = 0;
          >>
          in the base class.
          >>
          As far as I can see, there are two ways to proceed:
          >>
          1) make some virtual dummy function that the
          derived classes need to implement
          2) Hide the constructor of base as protected.
          >>
          >If your base class is going to be used polymorphically , you must declare
          >its destructor virtual anyway, so you don't need a "dummy" pure virtual
          >function. Just declare the destructor itself pure virtual:
          >>
          >virtual ~base() = 0
          >
          Of course!
          >
          This solution takes care of the case I'm working on
          right now, but how would one do this if there were
          some cleaning up to do on the base class level?
          >
          With the above solution one would have to call some
          base::cleanup() function in each of the derived
          destructors, right?
          Just because a function is pure virtual does not mean it cannot be
          implemented:

          #include <iostream>

          struct Base
          {
          virtual ~Base() = 0
          {
          std::cout << "~Base\n";
          }
          };

          struct Derived : public Base
          {
          ~Derived()
          {
          std::cout << "~D\n";
          }
          };

          int main() {
          Derived d;
          return 0;
          }

          --
          Erik Wikström

          Comment

          • terminator

            #6
            Re: Implementation of abstract classes

            On Sep 20, 8:12 pm, Erik Wikström <Erik-wikst...@telia. comwrote:
            On 2008-09-20 18:52, Rune Allnor wrote:
            >
            >
            >
            >
            >
            On 20 Sep, 18:40, Christian Hackl <ha...@sbox.tug raz.atwrote:
            Rune Allnor wrote:
            1) I would like to prevent users from making instances of
               class base
            2) There are no overloaded functions beween the base class
               and the derived classes, so I can not use the usual
            >
               virtual void overloaded_func tion() = 0;
            >
               in the base class.
            >
            As far as I can see, there are two ways to proceed:
            >
            1) make some virtual dummy function that the
               derived classes need to implement
            2) Hide the constructor of base as protected.
            >
            If your base class is going to be used polymorphically , you must declare
            its destructor virtual anyway, so you don't need a "dummy" pure virtual
            function. Just declare the destructor itself pure virtual:
            >
            virtual ~base() = 0
            >
            Of course!
            >
            This solution takes care of the case I'm working on
            right now, but how would one do this if there were
            some cleaning up to do on the base class level?
            >
            With the above solution one would have to call some
            base::cleanup() function in each of the derived
            destructors, right?
            >
            Just because a function is pure virtual does not mean it cannot be
            implemented:
            >
            #include <iostream>
            >
            struct Base
            {
              virtual ~Base() = 0
              {
                std::cout << "~Base\n";
              }
            >
            verrry interesting!!!! !!!!!!!!!!!!!!!
            are you sure??????????? ????????????

            regards,
            FM.

            Comment

            • James Kanze

              #7
              Re: Implementation of abstract classes

              On Sep 20, 6:07 pm, Rune Allnor <all...@tele.nt nu.nowrote:
              I have some classes which are derived from some base:
              class base {
              void foo();
              void bar();
              };
              class a : public base {
              };
              class b: public base{
              };
              The problem is as follows:
              1) I would like to prevent users from making instances of
              class base
              2) There are no overloaded functions beween the base class
              and the derived classes, so I can not use the usual
              virtual void overloaded_func tion() = 0;
              in the base class.
              As far as I can see, there are two ways to proceed:
              1) make some virtual dummy function that the
              derived classes need to implement
              2) Hide the constructor of base as protected.
              From a semantic point of view the latter solution
              seems the more elegant. Is this a good solution
              or are there traps or snags associated with it?
              I don't know about elegance, but the second solution is
              certainly the usual solution.

              --
              James Kanze (GABI Software) email:james.kan ze@gmail.com
              Conseils en informatique orientée objet/
              Beratung in objektorientier ter Datenverarbeitu ng
              9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

              Comment

              • Rune Allnor

                #8
                Re: Implementation of abstract classes

                On 20 Sep, 19:12, Erik Wikström <Erik-wikst...@telia. comwrote:
                Just because a function is pure virtual does not mean it cannot be
                implemented:
                >
                #include <iostream>
                >
                struct Base
                {
                  virtual ~Base() = 0
                  {
                    std::cout << "~Base\n";
                  }
                };
                Can this be correct? The way I understand

                virtual void foo() = 0;

                is that the statement inituializes a NULL
                pointer in the virtaul function table.
                It this is correct your code above will
                result in undefined behaviour.

                Rune

                Comment

                • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

                  #9
                  Re: Implementation of abstract classes

                  On 2008-09-21 16:55, Rune Allnor wrote:
                  On 20 Sep, 19:12, Erik Wikström <Erik-wikst...@telia. comwrote:
                  >
                  >Just because a function is pure virtual does not mean it cannot be
                  >implemented:
                  >>
                  >#include <iostream>
                  >>
                  >struct Base
                  >{
                  > virtual ~Base() = 0
                  > {
                  > std::cout << "~Base\n";
                  > }
                  >};
                  >
                  Can this be correct? The way I understand
                  >
                  virtual void foo() = 0;
                  >
                  is that the statement inituializes a NULL
                  pointer in the virtaul function table.
                  It this is correct your code above will
                  result in undefined behaviour.
                  Actually it is *not* a correct solution to Rune's problem, but not
                  because the reason you mentioned. The C++ standard does not mention
                  vtables or such things, it only defines what is supposed to happen and
                  leaves to the compiler to use the best technique to make it happen.

                  The "= 0" at the end of a function declaration means that the function
                  is pure virtual, and a class with a pure virtual function is abstract
                  (it can not be instantiated). This means that any derived classes have
                  to either implement the function or they will abstract too.

                  The reasons my code was not correct is that the standard does not allow
                  a pure function to be defined together with the declaration:

                  struct Foo
                  {
                  virtual void bar() = 0 { 1+1; } // Error
                  };

                  You can, however, provide the the definition separately:

                  struct Foo
                  {
                  virtual void bar() = 0;
                  };

                  void Foo::bar()
                  {
                  1 + 1;
                  }

                  You can also call a pure virtual function using a qualified expression:

                  struct Foo
                  {
                  virtual void bar() = 0;
                  };

                  void Foo::bar()
                  {
                  std::cout << "Foo::bar() \n";
                  }

                  struct Baz : public Foo
                  {
                  void bar()
                  {
                  std::cout << "Baz::bar() \n"
                  Foo::bar();
                  }
                  };

                  int main()
                  {
                  Foo* f = new Baz();
                  f->bar();
                  return 0;
                  }

                  Output:
                  Baz::bar()
                  Foo::bar()

                  --
                  Erik Wikström

                  Comment

                  • James Kanze

                    #10
                    Re: Implementation of abstract classes

                    On Sep 21, 4:55 pm, Rune Allnor <all...@tele.nt nu.nowrote:
                    On 20 Sep, 19:12, Erik Wikström <Erik-wikst...@telia. comwrote:
                    Just because a function is pure virtual does not mean it
                    cannot be implemented:
                    #include <iostream>
                    struct Base
                    {
                    virtual ~Base() = 0
                    {
                    std::cout << "~Base\n";
                    }
                    };
                    Can this be correct? The way I understand
                    virtual void foo() = 0;
                    is that the statement inituializes a NULL pointer in the
                    virtaul function table.
                    It might. All the standard says is that if a virtual function
                    call resolves to a pure virtual function, the behavior is
                    undefined.
                    It this is correct your code above will result in undefined
                    behaviour.
                    Only if you manage to have a virtual function call resolve to
                    Base::~Base. And I don't see any way of doing that that
                    wouldn't create undefined behavior anyway. (Basically, the only
                    way you could have it would be with an explicit destructor call
                    from a constructor or the destructor of Base.)

                    --
                    James Kanze (GABI Software) email:james.kan ze@gmail.com
                    Conseils en informatique orientée objet/
                    Beratung in objektorientier ter Datenverarbeitu ng
                    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                    Comment

                    • Juha Nieminen

                      #11
                      Re: Implementation of abstract classes

                      Rune Allnor wrote:
                      Can this be correct? The way I understand
                      >
                      virtual void foo() = 0;
                      >
                      is that the statement inituializes a NULL
                      pointer in the virtaul function table.
                      You understand wrongly. The "=0" part is nothing more than a way of
                      saying "pure". (The story goes that Stroustrup wanted to use the keyword
                      "pure", but the standardization committee didn't want any more
                      single-use keywords, so Stroustrup came up with the next best thing he
                      could come up with, which was adding "=0" to the method declaration.)

                      A pure virtual function is in all ways a regular virtual function,
                      with the exception that it *must* be implemented in a derived class, and
                      if there's a pure virtual function in the base class, that base class
                      cannot be instantiated all by itself. The difference between a virtual
                      function and a pure virtual function is purely semantical.

                      This means that a pure virtual function can have an implementation in
                      the exact same way as a regular virtual function can. You can call this
                      implementation by calling it explicitly, eg. Base::foo();

                      In the case of a pure virtual destructor, the destructor of the base
                      class is called automatically (so it doesn't need to be called explicitly).

                      Comment

                      • James Kanze

                        #12
                        Re: Implementation of abstract classes

                        On Sep 22, 12:29 am, Juha Nieminen <nos...@thanks. invalidwrote:

                        [...]
                        (The story goes that Stroustrup wanted to use the keyword
                        "pure", but the standardization committee didn't want any more
                        single-use keywords, so Stroustrup came up with the next best
                        thing he could come up with, which was adding "=0" to the
                        method declaration.)
                        I too have heard that there was a desire not to introduce new
                        keywords at that time, but you can't blame the committee: pure
                        virtual functions were present before the committee was founded.

                        --
                        James Kanze (GABI Software) email:james.kan ze@gmail.com
                        Conseils en informatique orientée objet/
                        Beratung in objektorientier ter Datenverarbeitu ng
                        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                        Comment

                        Working...