Classes

class Base {
public:
  virtual ~Base() = default; // make dtor virtual
   Base(Base&&) = default; // support moving
   Base& operator=(Base&&) = default;
   Base(const Base&) = default; // support copying
   Base& operator=(const Base&) = default;
   …
};

1. constructor could be deleted, but also any overload could be deleted as well:

bool isLucky(int number); // original function
bool isLucky(char) = delete; // reject chars
bool isLucky(bool) = delete; // reject bools
bool isLucky(double) = delete; // reject doubles and floats

2. Rule of Three (now Five).
The Rule of Three states that if you declare any of a copy constructor, copy assignment operator, or destructor, you should declare all three. (now including move)

3. Declare override functions in derived class with explicit declaration:

class Derived: public Base {
public:
  virtual void mf1() override;
  virtual void mf2(unsigned int x) override;
  virtual void mf3() && override;
  virtual void mf4() const override;
};

4. Destructor access level
When calling delete function destructor should be accessible at the place of the call. So by making destructor protected/private we can prevent using delete. (Note that if you don’t create destructor compiler would do it for you and make it public)

class Foo {
private:
  virtual ~Foo() = default;

public:
  void Release() {
    delete this;
  }
};

auto f = new Foo();
delete f;  <-- would NOT compile
f->Release(); <-- this is the only way now

5. Creating interface with factory

//base class for all classes
class IBase
{
protected:
    virtual ~IBase() = default; // protected destructor to prevent explicit call to delete
public:
    virtual void Release() = 0;  // this one will be used to delete the object
    IBase& operator=(const IBase&) = delete; // to prevent coping
};

//sample interface
class IDoer : public IBase
{
protected:
    ~IDoer() = default; // protected destructor
public:
    virtual void foo(bool b) = 0;
    static IDoer* CreateInstance(); // factory
};

//sample realization
class Doer: private IDoer
{
private:
    Doer();
protected:
    ~Doer();
public:
    void Release() override;
    void foo(bool b) override;

    friend IDoer* IDoer::CreateInstance();
};

Doer::Doer() {/* ... */}
Doer::~Doer() {/* ... */}
void Doer::Release() { delete this; }
void Doer::foo(bool b) {/* ... */}

IDoer* IDoer::CreateInstance()
{
    return static_cast<IDoer*>(new Doer());
}

Note that protected destructor must be in base class and in interface class. It has to be in the base class because in some cases a client can use IBase pointer. It has to be in the interface class because in case of its absence compiler would create default one.
Copy prevention could be just in the base class and it would work in the derived classes as well.

6. Creating interface with factory, using smart pointers

//single base class
class IBase
{
protected:
    IBase() = default;
    virtual ~IBase() = 0;  // protected, pure virtual destructor
    virtual void Delete(); // deleter

public:
    IBase(const IBase&) = delete;            // to prevent coping
    IBase& operator=(const IBase&) = delete; // to prevent assignment

    struct Deleter         // deleter class
    {
        void operator()(IBase* p) const { p->Delete(); }
    };

    friend struct IBase::Deleter;
};

IBase::~IBase() = default;
void IBase::Delete() { delete this; }

some useful tips (mostly for myself)