banner
Matrix

Matrix

Abyss
email
github

Petty C++ Constructor

Constructor is a special type of member function in OOP used to create objects and initialize member variables. In C++, constructors are similar to classes and do not have a return value.

Custom constructors are needed in the following situations:

  • Custom member initialization of a class
  • Calling a function when creating an object of a class

Constructors are generally public, but can also be declared as protected, private, etc.

Default Constructor#

A default constructor does not provide any parameters and can be implicitly defined when the class is defined. When not explicitly defined, the compiler will generate a default constructor. An example of a default constructor is:

class MyClass{
public:
  MyClass(){
    // do something..
  }
}

"Most Vexing Parse" about Default Constructor#

Because C++ analysis programs tend to lean towards declarations, there will be a warning when trying to use parentheses to call the default constructor generated by the editor:

class MyClass{};
int main(){
MyClass myClass();
  // warning C4930
}

In this example, MyClass myClass(); does not call the default constructor of MyClass to create the myClass object as expected. Instead, this line of code is actually interpreted as a function declaration, not an object declaration. Here, myClass is interpreted as a function that takes no parameters and returns an object of type MyClass.

This phenomenon is called the "Most Vexing Parse," a famous syntax parsing problem in the C++ language. This problem arises from the complexity of the C++ syntax, where certain syntax structures can be interpreted as multiple different things depending on the context. In this case, the compiler prioritizes interpreting the expression as a function declaration rather than an object construction.

Avoid this problem by explicitly creating the object:

int main() {
    MyClass myClass; 
}

Parameterized Constructor#

A parameterized constructor initializes with multiple parameters:

class MyClass{
public:
  int x, y;
  MyClass(int a, int b): x(a), y(b){
    // do something..
  }
}

Here, the member initialization expression list is used, with the expression taking the form:

identifier(argument)

The member initialization expression list consists of all expressions after the colon:

MyFunc(int a, int b, int c):
m_a(a), m_b(b), m_c(c){}

Copy Constructor#

A copy constructor is used to initialize a new object based on another object of the same type and is usually used in object copying scenarios:

class MyClass{
  public:
    int x, y;
    MyClass(const MyClass& mc):
    x(mc.x), y(mc.y) {}
}

In the above simple example, the members are scalars, so the compiler is sufficient to generate the copy constructor without needing to define it yourself. However, when the copy constructor needs to implement special behavior, such as allocating new memory, you need to implement the copy constructor yourself.

When defining a constructor, the copy assignment operator = needs to be overloaded.

// todo: copy assignment operator
// todo: operator overloading

Move Constructor#

The move constructor is a new feature introduced after C++11 and is used to transfer resources from one object to another. It is usually used in scenarios that support rvalue references, transferring ownership of existing object data to a new variable without copying the original data. It takes an rvalue reference as its first parameter, and any subsequent parameters must have default values. The move constructor can significantly improve program efficiency when passing large objects:

// todo: lvalues and rvalues
// todo: move assignment operator

class MyClass{
  public:
    char *str;
    MyClass(MyClass && obj): str(obj.str){
      obj.str = nullptr; // Avoid releasing memory when the original object is destructed
    }  
}

Delegating Constructor#

Delegating constructors are another new feature introduced after C++11, allowing one constructor to call another constructor within the same class, further decoupling the code:

class MyClass{
  public:
    int x, y, z;
    MyClass(int a, int b):x(a), y(b), z(0) {}
    MyClass(int a, int b, int c): Point(a, b) {z = c;}
}

Inheriting Constructor#

Inheriting constructors are a concept introduced after C++11, allowing constructors to be inherited from the base class using the using keyword:

class Base{
  public:
    Base(int x){};
};

class MyClass: public Base{
  using Base::Base; // Inherit constructors from Base
}

Explicit and Implicit Constructors#

Constructors declared with the explicit keyword can only be used for direct initialization, preventing the constructor from being accidentally called when implicit conversion is needed:

class MyClass {
public:
    explicit MyClass(int a) {}
};
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.