Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Design and Architecture
  4. Some thoughts about virtual methods [modified]

Some thoughts about virtual methods [modified]

Scheduled Pinned Locked Moved Design and Architecture
c++discussioncsharpphpasp-net
7 Posts 7 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    Lost User
    wrote on last edited by
    #1

    I have this situation and I want to know the opinions of other members on this. My language is C++. There is a base class that has the most vital virtual function called Job. Within the derived classes, there are several possibilities of things to be done before Job and/or after it. The Job would have to be done for about a hundred times* (The design has no problem, so if this sounds absurd it is only because I am not providing the exact details of the class). Also, this is supposed to run on multiple platforms, including .NET, mobile etc and not just native code on big fast CPUs. The core that contains this will remain in C++ and the necessary wrapping etc will be done to get it to run on the said platforms. In this scenario, considering speed and other things, which would be a better solution? 1. Have just the Job function and let the derived class do something like this

    DerivedClass::Job()
    {
    // pre operations
    // Base::Job() or the override
    // post operations
    }

    2. Have three virtual functions, PreJob, Job, PostJob and have the call to Job be bracketed like the following so that the code is neatly segregated

    JobCaller()
    {
    pBaseClass->PreJob()
    pBaseClass->Job()
    pBaseClass->PostJob()
    }

    EDIT: *about hundred for user interaction events like mouse clicks, screen taps etc depending on the platform. Basically, the user may "test" the load by playing with it.

    ...byte till it megahertz... my donation to web rubbish

    modified on Thursday, December 23, 2010 8:02 AM

    L P P D 4 Replies Last reply
    0
    • L Lost User

      I have this situation and I want to know the opinions of other members on this. My language is C++. There is a base class that has the most vital virtual function called Job. Within the derived classes, there are several possibilities of things to be done before Job and/or after it. The Job would have to be done for about a hundred times* (The design has no problem, so if this sounds absurd it is only because I am not providing the exact details of the class). Also, this is supposed to run on multiple platforms, including .NET, mobile etc and not just native code on big fast CPUs. The core that contains this will remain in C++ and the necessary wrapping etc will be done to get it to run on the said platforms. In this scenario, considering speed and other things, which would be a better solution? 1. Have just the Job function and let the derived class do something like this

      DerivedClass::Job()
      {
      // pre operations
      // Base::Job() or the override
      // post operations
      }

      2. Have three virtual functions, PreJob, Job, PostJob and have the call to Job be bracketed like the following so that the code is neatly segregated

      JobCaller()
      {
      pBaseClass->PreJob()
      pBaseClass->Job()
      pBaseClass->PostJob()
      }

      EDIT: *about hundred for user interaction events like mouse clicks, screen taps etc depending on the platform. Basically, the user may "test" the load by playing with it.

      ...byte till it megahertz... my donation to web rubbish

      modified on Thursday, December 23, 2010 8:02 AM

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      (2) is the cleaner approach, obviously. if PreJob+Job+PostJob is more than 100 lines of code (dynamically speaking), then the difference in performance will be unnoticeable. if mosr jobs have different PreJob and PostJob functionality (never shared with the base class), the added structure doesn't bring you much. So look at the statistics and decide for yourself. :)

      Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

      Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

      X 1 Reply Last reply
      0
      • L Lost User

        I have this situation and I want to know the opinions of other members on this. My language is C++. There is a base class that has the most vital virtual function called Job. Within the derived classes, there are several possibilities of things to be done before Job and/or after it. The Job would have to be done for about a hundred times* (The design has no problem, so if this sounds absurd it is only because I am not providing the exact details of the class). Also, this is supposed to run on multiple platforms, including .NET, mobile etc and not just native code on big fast CPUs. The core that contains this will remain in C++ and the necessary wrapping etc will be done to get it to run on the said platforms. In this scenario, considering speed and other things, which would be a better solution? 1. Have just the Job function and let the derived class do something like this

        DerivedClass::Job()
        {
        // pre operations
        // Base::Job() or the override
        // post operations
        }

        2. Have three virtual functions, PreJob, Job, PostJob and have the call to Job be bracketed like the following so that the code is neatly segregated

        JobCaller()
        {
        pBaseClass->PreJob()
        pBaseClass->Job()
        pBaseClass->PostJob()
        }

        EDIT: *about hundred for user interaction events like mouse clicks, screen taps etc depending on the platform. Basically, the user may "test" the load by playing with it.

        ...byte till it megahertz... my donation to web rubbish

        modified on Thursday, December 23, 2010 8:02 AM

        P Offline
        P Offline
        Pete OHanlon
        wrote on last edited by
        #3

        Unless the optimizer has changed much, if PreJob and PostJob don't do anything in a class, I believe they are optimized out. It's been a long time since I've done any serious C++, but I seem to remember that this is the case. As the base class is only going to be using VTable lookups here anyway, the overhead should not be significant in real terms.

        I'm not a stalker, I just know things. Oh by the way, you're out of milk.

        Forgive your enemies - it messes with their heads

        My blog | My articles | MoXAML PowerToys | Onyx

        1 Reply Last reply
        0
        • L Luc Pattyn

          (2) is the cleaner approach, obviously. if PreJob+Job+PostJob is more than 100 lines of code (dynamically speaking), then the difference in performance will be unnoticeable. if mosr jobs have different PreJob and PostJob functionality (never shared with the base class), the added structure doesn't bring you much. So look at the statistics and decide for yourself. :)

          Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

          Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

          X Offline
          X Offline
          Xpnctoc
          wrote on last edited by
          #4

          I agree with Luc on performance issues, but I disagree when he say that the added structure would not be beneficial. If your core Job function cannot stand on its own (i.e., requires pre- and post- function, regardless of how different those functions may be from derived class to derived class), then I personally would absolutely declare the Pre- and Post- as "abstract" methods to ensure that every new derived class you create implements Pre- and Post-. This is exactly why "abstract" declarations were invented. You could then invoke Pre- and Post- from Base::Job and not have to implement a Derived::Job method at all. Like this (I apologize if my syntax isn't perfect. Been doing a lot of C++/CLI, so I might not be completely right in native C++ syntax):

          class Base
          {
          public:
          virtual void Job()
          {
          Pre();
          // actual job code here
          Post();
          }
          protected:
          virtual void Pre() abstract;
          virtual void Post() abstract;
          }

          class Derived : public Base
          {
          protected:
          virtual void Pre() override
          {
          //derived-specific pre-job code here
          }

          virtual void Post() override
          {
          //derived-specific post-job code here
          }
          }

          // Calling Code:
          Derived* myDerived = new Derived();
          myDerived->Job(); // invokes Job in base class, which in turn invokes Pre/Post in derived class.

          B 1 Reply Last reply
          0
          • X Xpnctoc

            I agree with Luc on performance issues, but I disagree when he say that the added structure would not be beneficial. If your core Job function cannot stand on its own (i.e., requires pre- and post- function, regardless of how different those functions may be from derived class to derived class), then I personally would absolutely declare the Pre- and Post- as "abstract" methods to ensure that every new derived class you create implements Pre- and Post-. This is exactly why "abstract" declarations were invented. You could then invoke Pre- and Post- from Base::Job and not have to implement a Derived::Job method at all. Like this (I apologize if my syntax isn't perfect. Been doing a lot of C++/CLI, so I might not be completely right in native C++ syntax):

            class Base
            {
            public:
            virtual void Job()
            {
            Pre();
            // actual job code here
            Post();
            }
            protected:
            virtual void Pre() abstract;
            virtual void Post() abstract;
            }

            class Derived : public Base
            {
            protected:
            virtual void Pre() override
            {
            //derived-specific pre-job code here
            }

            virtual void Post() override
            {
            //derived-specific post-job code here
            }
            }

            // Calling Code:
            Derived* myDerived = new Derived();
            myDerived->Job(); // invokes Job in base class, which in turn invokes Pre/Post in derived class.

            B Offline
            B Offline
            Bernhard Hiller
            wrote on last edited by
            #5

            I would also add a

            protected virtual void Actual()

            containing the actual job code, and call that from the Job() method. Not only does it make things clearer, you can also be sure that the actual job code will have to be overridden in a derived class soon.

            1 Reply Last reply
            0
            • L Lost User

              I have this situation and I want to know the opinions of other members on this. My language is C++. There is a base class that has the most vital virtual function called Job. Within the derived classes, there are several possibilities of things to be done before Job and/or after it. The Job would have to be done for about a hundred times* (The design has no problem, so if this sounds absurd it is only because I am not providing the exact details of the class). Also, this is supposed to run on multiple platforms, including .NET, mobile etc and not just native code on big fast CPUs. The core that contains this will remain in C++ and the necessary wrapping etc will be done to get it to run on the said platforms. In this scenario, considering speed and other things, which would be a better solution? 1. Have just the Job function and let the derived class do something like this

              DerivedClass::Job()
              {
              // pre operations
              // Base::Job() or the override
              // post operations
              }

              2. Have three virtual functions, PreJob, Job, PostJob and have the call to Job be bracketed like the following so that the code is neatly segregated

              JobCaller()
              {
              pBaseClass->PreJob()
              pBaseClass->Job()
              pBaseClass->PostJob()
              }

              EDIT: *about hundred for user interaction events like mouse clicks, screen taps etc depending on the platform. Basically, the user may "test" the load by playing with it.

              ...byte till it megahertz... my donation to web rubbish

              modified on Thursday, December 23, 2010 8:02 AM

              P Offline
              P Offline
              Paul Michalik
              wrote on last edited by
              #6

              Have you looked at Aspect Oriented Programming (AOP)? It provides a great alternative to inheritance in cases like yours. Don't know how complicated that triplet(?) of Pre, Actual, and Post calls will become, but my experience tells me that the orchestration of overridden virtual calls of that kind quickly becomes a nightmare... A good half-way to AOP are design patterns like chain of responsibility - in many cases this gives you larger flexibility and better control over the behaviour than (often hacky) orchestration of calls to overridden methods. By the way, if you are on native C++, have a look at the C++ idiom called Wrap http://www2.research.att.com/~bs/wrapper.pdf - an interesting possibility to get compile time configurable Aspect-like behaviour. Often (but not always) the flexibility supersedes the one of polymorphic inheritance based implementation, could have issues about interoperability though... Cheers, Paul

              1 Reply Last reply
              0
              • L Lost User

                I have this situation and I want to know the opinions of other members on this. My language is C++. There is a base class that has the most vital virtual function called Job. Within the derived classes, there are several possibilities of things to be done before Job and/or after it. The Job would have to be done for about a hundred times* (The design has no problem, so if this sounds absurd it is only because I am not providing the exact details of the class). Also, this is supposed to run on multiple platforms, including .NET, mobile etc and not just native code on big fast CPUs. The core that contains this will remain in C++ and the necessary wrapping etc will be done to get it to run on the said platforms. In this scenario, considering speed and other things, which would be a better solution? 1. Have just the Job function and let the derived class do something like this

                DerivedClass::Job()
                {
                // pre operations
                // Base::Job() or the override
                // post operations
                }

                2. Have three virtual functions, PreJob, Job, PostJob and have the call to Job be bracketed like the following so that the code is neatly segregated

                JobCaller()
                {
                pBaseClass->PreJob()
                pBaseClass->Job()
                pBaseClass->PostJob()
                }

                EDIT: *about hundred for user interaction events like mouse clicks, screen taps etc depending on the platform. Basically, the user may "test" the load by playing with it.

                ...byte till it megahertz... my donation to web rubbish

                modified on Thursday, December 23, 2010 8:02 AM

                D Offline
                D Offline
                dasblinkenlight
                wrote on last edited by
                #7

                From a perfectionists' point of view, having job callers deal with sequences of calls violates encapsulation: job callers do not need to know that a job requires a "setup" and a "cleanup" steps. To hide the internals from your callers while keeping the distinction in your implementations, make an abstract class with a skeleton method, then override pre/post/job methods as needed in your derived classes. This technique is commonly known as the "Template Method" pattern[^]; I prefer "skeleton" to avoid confusion with C++ templates.

                AbstractClass::Job()
                {
                doPreJob();
                doJob();
                doPostJob();
                }

                DerivedClass::doPreJob() {}

                DerivedClass::doJob() {}

                DerivedClass::doPostJob() {}

                JobCaller()
                {
                pAbstractClass -> Job();
                }

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups