Click here to Skip to main content
13,045,641 members (68,726 online)
Click here to Skip to main content
Add your own
alternative version


15 bookmarked
Posted 28 Sep 2003

Enforcing function call order in C++

, 29 Sep 2003
Rate this:
Please Sign up or sign in to vote.
A simple set of macros to enforce function call order in C/C++.

Assertion thrown


When declaring an interface (as a class for example), there is a need to define the allowed calling order of functions. For example, Init() must be called before any other function, and nothing should be called after Shutdown().

In the spirit of design by contract, I wrote this tiny class + macros to make such rules enforceable in runtime.

See also:

This code was tested on VC 6 and should work on any C++ compiler.


Design By Contract (DBC) is an issue that many people talk about but I did not see much practical work in the environment I work with (C++). DBC is all about clearly defining what your code should do (This might not be the best definition, but it will do for now).

While working on a complex project I found a bug caused by forgetting to call Init() before the function I needed. Of course, it happened only in certain control flows, to make it more challenging.

The solution: Check in runtime that things happen as you expect them to be. Putting ASSERT()s helps but it is not enough by itself.

Using the code

The code consists of one class and a few macros to make the source readable. For example, the statement function B::foo() should be called after Init() and not after shutdown() is written as:

void B::foo()
    // do something here

The full list of macros you can use (see also the .h file):

  • Enter(name) - call this as the first thing in your function, unless this is your Init().
  • Called(name) - return true if function name was already called (anytime in the past).
  • FirstCall - return true if no functions were called, including this function.
  • Prev(name) return true if name was called just before the current function.
  • Require(boolean expression) will blow a fuse if expression evaluates to false. Currently it is simply ASSERT().

      To use the code, include DBC_EnforceOrder.h and in the class declaration add a macro:

      class B
      // ...
          DBC_Data;  // add this macro to your data declaration section

      In each function that may influence the state of "what is allowed to be called next", you have to add the Enter(name) macro as in the B::foo().

      Finally, to turn it off, make sure the macro _EnforceCallOrder is undefined. Currently it is defined in the H file.


      • In every function (of interest) you must add ' Enter("function_name"). In another article I wrote, there is a way around it using symbol table engine - but this complicates the code enormously.
      • I could add special rules such as LAST_FUNCTION, and then check for this status in the Enter() call. I chose not to do it for the tradeoff between simplicity and elegance.

      Future additions

      • So far, only REQUIRE (i.e. precondition) is implemented. It would be nice to add ENSURE for post condition checking as well.
      • call STACK_TRACE() from Enter() to have the full monti.

      Points of interest

      I wrote this code after failing to find in the Internet, the exact solution to what I needed. There are plenty of articles on DBC, but not so much frameworks to work with. And remember the KISS principle!


      • 2003-09-25: First release
    • License

      This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

      A list of licenses authors might use can be found here


      About the Author

      Noam Cohen
      Israel Israel
      Noam is working at Harmonic Lightwave (

      You may also be interested in...

      Comments and Discussions

      GeneralstackTrace.dll Pin
      Christophe MOUSTIER7-Oct-03 1:52
      memberChristophe MOUSTIER7-Oct-03 1:52 
      GeneralIt's a good solution, Pin
      WREY30-Sep-03 8:07
      memberWREY30-Sep-03 8:07 
      GeneralRe: It's a good solution, Pin
      saltynuts20021-Oct-03 16:31
      membersaltynuts20021-Oct-03 16:31 
      GeneralRe: It's a good solution, Pin
      WREY2-Oct-03 5:32
      memberWREY2-Oct-03 5:32 
      GeneralSorry, but I don't agree Pin
      Patje29-Sep-03 23:28
      memberPatje29-Sep-03 23:28 
      GeneralRe: Sorry, but I don't agree Pin
      Noam Cohen30-Sep-03 2:10
      memberNoam Cohen30-Sep-03 2:10 
      GeneralRe: Sorry, but I don't agree Pin
      KevinHall30-Sep-03 3:48
      memberKevinHall30-Sep-03 3:48 
      Generalusing it in RELEASE build Pin
      Noam Cohen30-Sep-03 21:10
      memberNoam Cohen30-Sep-03 21:10 
      GeneralRe: Sorry, but I don't agree Pin
      armentage30-Sep-03 5:04
      memberarmentage30-Sep-03 5:04 
      GeneralRe: Sorry, but I don't agree Pin
      trendkiller4310-Oct-03 9:07
      membertrendkiller4310-Oct-03 9:07 
      GeneralEnumerations Pin
      KarstenK29-Sep-03 22:02
      memberKarstenK29-Sep-03 22:02 
      GeneralRe: Enumerations Pin
      Noam Cohen30-Sep-03 1:29
      memberNoam Cohen30-Sep-03 1:29 
      QuestionUse boolean variables? Pin
      Daemin29-Sep-03 18:01
      memberDaemin29-Sep-03 18:01 
      AnswerRe: Use boolean variables? Pin
      anandparanjpe29-Sep-03 20:38
      memberanandparanjpe29-Sep-03 20:38 

      General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

      Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

      Permalink | Advertise | Privacy | Terms of Use | Mobile
      Web02 | 2.8.170713.1 | Last Updated 30 Sep 2003
      Article Copyright 2003 by Noam Cohen
      Everything else Copyright © CodeProject, 1999-2017
      Layout: fixed | fluid