Useful links:

CRTP Sample Code

template <class Self>
struct Base {
    // short cut to reference to dervied class
    Self& self() { return static_cast<Self&>(*this); };

    // reuse base code
    int algorithm(int x) {
        if (x > 42)
            x = self().downsize(x);
        x = self().crunch(x);
        return x;
    };

    int downsize(int x) { return x % 42; };
    int crunch(int x) { return -x; };

    // static polymorphism
    int run() {
        return std::static_cast<Self*>(this)->_run_impl();
    }
};

struct Derived : Base<Derived> {
    // overriding base code
    int downsize(int x) {
        while (x > 42) x /= 2;
        std::cout << "down!" << std::endl;
        return x;
    };

    // static polymorphism
    int _run_impl() {
        return 1;
    }
};

// better type safety
template <class T>
int foo(Base<T> &actor)
{
  return actor.algorithm(314);
}

// more duck-typing
template <class T>
int bar(T &actor)
{
  return actor.algorithm(314);
}

int main() {
  Derived d;
  std::cout << d.algorithm(420);
}

CRTP versus virtual functions

CRTP is a purely compile-time construct, meaning there’s no runtime overhead associated. Calling a virtual function through a base class reference (usually) requires a call through a pointer to function and thus incurs indirection costs and prevents inlining.

CRTP versus simply implementing everything in Derived

Base class code reuse.

Reference:

  1. Confusion about CRTP static polymorphism

Can Virtual Classes(Interfaces) in C++ have Member Variables?

Strictly speaking, there is no such thing as a “virtual class” or “interface” in C++. If there is, it is artificial, i.e., developer-enforced. Generally, an interface has these characteristics:

So the answer is

Generally, it is considered better to make interfaces, pure interfaces. If there is really some information that is common to all derived classes (or simply to several of them), simply make that info another class and derive the implementation class from that also:

class Base {
    virtual void method1() = 0; // pure virtual method 1
    // virtual methods...
    // no data
};
struct Common {
    Data x;
    // ...
};
class Derived : public Base, public Common {
    // methods and data...
};

Reference:

  1. Can Virtual Classes in C++ have Member Variables?
  2. Bjarne Stroustrup’s C++ Style and Technique FAQ

What is the Non-virtual Interface Design Pattern and When to Use It?

The essence of the non-virtual interface pattern is that you have private virtual functions, which are then called(invoked) by public non-virtual functions (the non-virtual interface).

Advantage: The base class has more control over its behavior (the derived class can override less part of the whole thing).

Reference:

  1. Non-virtual interface design pattern in C#/C++.

Shall I use virtual constructors/destructors?

There are no virtual constructors. From Bjarne Stroustrup’s C++ Style and Technique FAQ

A virtual call is a mechanism to get work done given partial information. In particular, “virtual” allows us to call a function knowing only any interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create. Consequently, a “call to a constructor” cannot be virtual.

However virtual destructors are especially useful when you might potentially delete an instance of a derived class through a pointer to a base class:

class Base {
    // some virtual methods
};

class Derived : public Base {
    ~Derived() {
        // Do important cleanup
    }
}

Base *b = new Derived();
// use b
delete b; // **Here's the problem!**

Always make base classes have virtual destructors when they are meant to be manipulated polymorphically. (Effective C++ Item 7)

Reference:

  1. When to use virtual destructors?

What Are Static Polymorphism and Dynamic Polymorphism?

todo.

Implicit inline When Methods Written in Class Body

Inside the class body is considered to be inline by the compiler. If you implement outside of body, but still in header, you have to mark the method as ‘inline’ explicitly.

namespace test_ns{

class TestClass{
public:
    // without this inline, multiple definition error will occur!
    inline void testMethod();
};

void TestClass::testMethod(){
    // some code here...
}

} // end namespace test_ns

Reference:

  1. multiple definition error including c++ header file with inline code from multiple sources