Visitor pattern and double dispatch in C++.

Share Button

In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures.

In essence, the visitor allows one to add new virtual functions to a family of classes without modifying the classes themselves; instead, one creates a visitor class that implements all of the appropriate specializations of the virtual function. The visitor takes the instance reference as input, and implements the goal through double dispatch.

At first glance, double dispatch appears to be a natural result of function overloading. Function overloading allows the function called to depend on the type of the argument. Function overloading however is done at compile time using “name mangling” where the internal name of the function has the argument’s type encoded in it. So for example function foo(int) would internally be called “__foo_i” and function foo() would be called “__foo_v” (“v” for void). So there is no runtime overhead because there is no name collision and calling an overloaded function goes through at most one virtual table just like any other function. Dynamic dispatch is only based on the type of the calling object. Consider the following example:

which will have output as:

The last two outputs are not what’s expected by us. We are expecting to see output as “Person uses an Hammer” and “ycshao uses an Hammer”. This happens because that while virtual functions are dispatched dynamically in C++, function overloading is done statically. This problem can be solved by double dispatch using a visitor pattern as follows.

And the outputs will be what we expected:

References:

Visitor pattern

Double dispatch

Option types

Share Button

Naming conventions are used to help identify properties common to many different types of options. These include:

  • Vanilla option – any option that is not exotic.
    -  European option – an option that may only be exercised on expiration.
    -  American option – an option that may be exercised on any trading day on or before expiry.
    -  Bermudan option – an option that may be exercised only on specified dates on or before expiration.
  • Exotic option – any of a broad category of options that may include complex financial structures.
    -  Barrier option – any option with the general characteristic that the underlying security’s price must pass a certain level or “barrier” before it can be exercised.

Effective C++ item 4: Make sure that objects are initialized before they’re used.

Share Button
  1. For most types, a single call to a copy constructor is more efficient – sometimes much more efficient – than a call to the default constructor followed by a call to the copy assignment operator.
  2. Base classes are initialized before derived classes, and within a class, data members are initialized in the order in which they are declared.Once you’ve taken care of explicitly initializing non-member objects of built-in types and you’ve ensured that your constructors initialize their base classes and data members using the member initialization list, there’s only one more thing to worry about. That’s the order of initialization of non-local static objects defined in different translation units.Let’s first talk about static objects. A static object is one that exists from the time it’s constructed until the end of the program. Stack and heap-based objects are thus excluded. Included are global objects, objects defined at namespace scope, objects declared static inside classes, objects declared static inside functions, and objects declared static at file scope. Static objects inside functions are known as local static objects (because they are local to a function), and the other kinds of static objects are known as non-local static objects. Static objects are destroyed when the program exits, i.e., their destructors are called when main finishes executing.

    A translation unit is the source code giving rise to a single object file. It’s basically a single source file, plus all of its #include files.

  3. Now let’s discuss a real problem about initialization of non-local static objects. Imagine at least two separately compiled source files, each of which contains at least one non-local static object (i.e., an object that’s global, at namespace scope, or static in a class or at file scope). If initialization of a non-local static object in one translation unit uses a non-local static object in a different translation unit, the object it uses could be uninitialized, because the relative order of initialization of non-local static objects defined in different translation units is undefined.
    Let’s see an example:
    In fileSystem.h file, you defined

And in a.cpp file, you have:

Then suppose somebody use your code like this in b.h and b.cpp:

If you’re going to define an object:

Unless theFileSystem is initialized before tempDir, tempDir’s constructor will attempt to use theFileSystem before it’s been initialized.

One solution to this is to make a small design change. All that has to be done is to move each non-local static object into its own function, where it’s declared static. These functions return references to the objects they contain. Then call the functions instead of referring to the objects. In other words, non-local static objects are replaced with local static objects. C++ guarantee that local static objects are initialized when the object’s definition is first encountered during a call to that function. Here’s the technique applied to both theFileSystem and tempDir:

The reference-returning functions dictated by this scheme are always simple: define and initialize a local static object on line 1, return it on line 2. This simplicity makes them excellent candidates for inlining, especially if they’re called frequently.

Reference:
“Effective C++” Third Edition by Scott Meyers.

Effective C++ item 3: Use const whenever possible

Share Button
    1. Const return value for overload operator.

If you miss the first “const”, one simple typo can make it wrong:

In the code above, I know you want to type “==” not “=”. But compiler will happily generate code for you, and maybe you have to spend hours to debug. All you need to do is use const to prevent unwanted behavior.

    1. Const member functions.

Let’s see an example:

And then to illustrate how const member function works:

    1. To avoid duplication code in const and non-const member functions.

Typically corresponding const and non-const member functions are very similar, to avoid code duplication, we make non-const member function call const member function with certain cast:

As you can see, the code has two casts, not one. We want the non-const operator[] to call the const one, but if, inside the non-const operator[], we just call operator[], we’ll recursively call ourselves. So we cast *this from TextBlock& to const TextBlock&. The static_cast is to remove the const from the const operator[]’s return value.

    1. Use mutable key word to free non-static data members from the constraints of constness.

For example:

Here, m_textLength can be changed in const member function.

Reference:
“Effective C++” Third Edition by Scott Meyers.

Effective C++ item 2: Prefer consts, enums, and inlines to #defines.

Share Button
    1. The enum hack is preferred to define constant for integers, and const is preferred to define other variables than #define.

Here is an example for enum hack:

To limit the scope of a constant to a class, we have to make it a member. And to ensure there’s at most one copy of the constant, we must make it a static member:

Above is a declaration for RATIO, not a definition. C++ requires that we provide a definition for anything we use, but class-specific constants that are static and of integral type(e.g., integers, doubles,  bools) are an exception. As long as we don’t take their address, we can declare them and use them without providing a definition. If you do want to take the address, then provide a definition like this:

We put this in a .cpp file not a .h file. Because the initial value of class constants is provided where the constant is declared, no initial value is permitted at the point of definition.

    If you want to define a char or string type static const variable, you have to do like this:
      In .h file:

      In .ccp file:

 

    1. Function-like macro can behave very differently than what you think if ++/– is used, since arguments of a macro may be interpreted several times instead of just one time in function call.

So if you define:

and you will get unexpected behavior:

Reference:
“Effective C++” Third Edition by Scott Meyers.

Effective C++ item 1: View C++ as a federation of languages.

Share Button

Meyers suggests us to view c++ as a federation of languages since a rule may apply to one sub-language but not others. It is easier and more straight forward to treat c++ as a set of sub-languages.

  1. C: Blocks, statements, the preprocessor, built-in data types, arrays, pointers, etc.
  2. Object-Oriented C++: Classes, encapsulation, inheritance, polymorphism, virtual functions, etc.
  3. Template C++: Template metaprogramming(TMP). It’s not uncommon for rules of good programming to include special template-only clauses.
  4. The STL: The STL has particular ways of doing things, and when you’re working with the STL, you need to be sure to follow its conventions.

Reference:

    How to clone/copy SVN repository to another computer

    Share Button

    Since I’m not running SVN on server, instead, I created SVN repository on local machines, So I have to find way to access my repository remotely from other machines. Here is a simple way to access my repository from other machines, but not directly remote to my repository:

      1. Set up your environment variable SVNREPO(where your repository is) and SHARE(where stores necessary files. Your can choose whatever cloud folder such as dropbox or Ubuntu one folder). (See how to set up environment variable here)
      2. Edit your .bashrc file and add these two lines:

      1. Restart your linux terminal.
      2. Export your repository to shared cloud folder:

      1. On machine 2, setup accordingly as above. If your file structure is the same as your machine 1, just redo step 1 and 2, and restart terminal.
      2. On machine 2, import your repository:

    1. Done.

    Reference:
    Migrating a Subversion repository from one machine to another

    SVN: local delete/edit, incoming delete upon update

    Share Button

    Have you ever encounter such a weird situation that you have no idea what happend and how to resolve this SVN conflict:

    or

    This is because that file has been deleted from repository and you either edited or deleted it in your working directory. Even though it’s the right thing for you to do to delete the file locally, SVN will not satisfy with that! And here is a simple way to resolve this conflict: (NOTE: Here I assume you indeed want to delete that file. If you don’t, please BACKUP that file first and after done all steps here, commit it back to repository.)

      1. In your working directory, recreate that conflicting file:

      1. Revert that file to the state SVN likes (that means deleted):

      1. Now delete that file:

      1. Conflict resolved:

    1. Done.

    Use vim/gvim as a file manager

    Share Button

    Maybe it is the case that your screen is small or you don’t have enough screens, you cannot open many terminals and editors. In this case, you probably want to use your editor as a file manager like windows explorer. Vim is a perfect tool for that. (Emacs also can do that, but I don’t use Emacs….. sorry)

    • Use :Ex (mnemonic: Explorer) to bring up file explore, and you can view, delete, open, rename, move and etc.
    • You can also use :Sex (Sex?? Split explorer), :Vex (Vertical split explorer), and :Tex (new tab explorer).
    • In file explorer, you can press <F1> to get more awesome feature!
    • Actualy, if you direct vim a directory, it opens file explorer.

    Pure virtual function called in abstract classes (c++ polymorphism)

    Share Button

    I learned that pure virtual function can be called in abstract classes.
    Let’s look at an example:

    The output will be:

    Reference:
    Polymorphism