C++ const members and static members

const members and static members

Cont members of class

const data members

Const data members can only be initialized through a constructor initializer list.

class Box {<!-- -->
private:
    const int length; //Length
const int width; //width
const int height; //height
public:
    Box();
    Box(int H, int W, int L);
};
Box::Box(int H, int W, int L) : height{<!-- --> H }, width{<!-- --> W }, length{<!-- --> L } {<!-- -->}
Box::Box() : height{<!-- --> 1 }, width{<!-- --> 2 }, length{<!-- --> 3 } {<!-- --> }

Const data members can set initial values within the class.

class Box {<!-- -->
private:
    const int length = 3; //Length
const int width = 4; //Width
const int height = 5; //Height
public:
    Box() = default;
    Box(int H, int W, int L);
};
Box::Box(int H, int W, int L) : height{<!-- --> H }, width{<!-- --> W }, length{<!-- --> L } {<!-- -->}

const member function

By adding the const keyword after the parameter list of a function, a member function that uses const is called a const member function.
Const member functions can only reference data members in this class, but cannot modify them.

class Box {<!-- -->
private:
    const int length; //Length
const int width; //width
const int height; //height
public:
    Box() = default;
    Box(int H, int W, int L);
    void Print(void) const; //Declaration, print length, width, height
};
Box::Box(int H, int W, int L) : height{<!-- --> H }, width{<!-- --> W }, length{<!-- --> L } {<!-- -->}
void Box::Print(void) const //The definition is also modified with const
{<!-- -->
    cout << length << ' ' << width << ' ' << height << endl;
}

Const member functions can be called by both const and non-const objects, while non-const member functions can only be called by non-const objects.
If a const member function returns *this as a reference, its return type will be a constant reference.

class Box {<!-- -->
private:
    int length; //Length
int width; //width
int height; //height
public:
    Box() = default;
    Box(int H, int W, int L);
    const Box & amp; Print(void) const; //return constant reference
};
Box::Box(int H, int W, int L) : height{<!-- --> H }, width{<!-- --> W }, length{<!-- --> L } {<!-- -->}
const Box & amp; Box::Print(void) const //Return constant reference
{<!-- -->
    cout << length << ' ' << width << ' ' << height << endl;
    return *this;
}

Constructors cannot be declared const.

mutable data members

If you want to modify the data member through a const member function, you can declare the data member as mutable.

class Box {<!-- -->
private:
    int length; //Length
int width; //width
    mutable int height; //Height, declared as mutable
public:
    Box() = default;
    Box(int H, int W, int L);
    int Volume(int h) const; //Modify the height of the box and find the volume
};
Box::Box(int H, int W, int L) : height{<!-- --> H }, width{<!-- --> W }, length{<!-- --> L } {<!-- -->}
int Box::Volume(int h) const //Modify the height of the box and find the volume
{<!-- -->
    height = h; //Box height can be modified
    return length * width * height;
}

const object

When defining an object, you can add the keyword const to specify the object as a const object.
A const object must have an initial value, and all data members in the object cannot be modified.
A const object can only call its const member functions (except for destruction and construction). Const member functions are the only external interface of const objects.
Const member functions can access data members in const objects, but they are still not allowed to modify the values of data members in const objects.

const Box B1; //Call parameterless constructor
const Box B2{<!-- -->1,2,3}; //Call parameterized constructor
B1.Print(); //Call const member function
B1.Volume(10); //mutable data members can be modified

Aggregation class

An aggregate class allows users to directly access its members and has a special initialization syntax.
We say a class is aggregated when it satisfies the following conditions:

  • All members are public.
  • No constructor is defined.
  • There is no in-class initializer.
  • There is no base class and no virtual functions.

Literal constant class

An aggregate class whose data members are all literal types is a literal constant class.
A class is a literal constant class if it is not an aggregate class but meets the following requirements:

  • Data members must be literal types.
  • A class must have at least one constexpr constructor.
  • If a data member contains an in-class initializer, the initializer for the built-in type member must be a constant expression; or if the member is of a class type, the initializer must use the member’s own constexpr constructor.
  • Classes must use the default definition of a destructor.

constexpr constructor

Although the constructor cannot be const, the constructor of a literal constant class can be a constexpr function.
The constexpr constructor must initialize all data members. The initial value is either the constexpr constructor or a constant expression.
The constexpr constructor is used to generate constexpr objects and the parameters or return types of constexpr functions.

A literal constant class

class Birthday
{<!-- -->
private:
    unsigned int year = 0; //year
    unsigned int month = 0; //month
    unsigned int day =0; //day
public:
    constexpr Birthday() = default;
    constexpr Birthday(unsigned int y, unsigned int m, unsigned int d); //constexpr constructor
    void Print(void) const;
};
constexpr Birthday::Birthday(unsigned int y, unsigned int m, unsigned int d) :
    year{<!-- --> y }, month{<!-- --> m }, day{<!-- --> d } {<!-- -->}
void Birthday::Print(void) const
{<!-- -->
    cout << year << "Year" << month << "Month" << day<< "Day" << endl;
}

constexpr object

A constexpr object can only call its constexpr member functions.
Constexpr objects can only be generated by calling the constructor.

 constexpr Birthday b{<!-- --> 2012,3,12 };
    b.Print();

Static members

Static data members

Variables that are part of a class but not part of a class object are called static members.
Static data members cannot be initialized using constructors and can only be initialized outside the class.
When initializing static data members outside a class, the static keyword cannot be repeated.

class Box {<!-- -->
private:
    int length; //length
int width; //width
    int height; //height
    static int number; //Count the number of boxes
public:
    Box();
    Box(int H, int W, int L);
};
int Box::number = 0; //Initialize static data members outside the class

Const static data members can specify initial values within the class.
However, static data members must be const of integral or enumeration type, or constexpr of literal type, and the initializer must be a constant-expression.

class Box {<!-- -->
private:
    int length; //Length
int width; //width
    int height; //height
    const static int number = 0; //const static data member
public:
    Box();
    Box(int H, int W, int L);
};

Static data members are allocated space when the program starts and are released when the program ends.
All objects of this class share one or more static data members.

Static member function

Similarly, functions that require access to class members without being called through a specific object are called static member functions.
Static member functions are not bound to any object, have no this pointer, and cannot access non-static members of this class.
Static member functions cannot be declared const.

class Box {<!-- -->
private:
    int length; //Length
int width; //width
    int height; //height
    static int number; //Count the number of boxes
public:
    Box();
    Box(int H, int W, int L);
    static int GetNumber(void); //static member function
};
int Box::number = 0;
Box::Box(int H, int W, int L) : height{<!-- --> H }, width{<!-- --> W }, length{<!-- --> L }
{<!-- -->
    number + = 1; //Every time a box is created, number increases by one
}
Box::Box() : height{<!-- --> 1 }, width{<!-- --> 2 }, length{<!-- --> 3 }
{<!-- -->
    number + = 1; //Every time a box is created, number increases by one
}
int Box::GetNumber(void) //static member function
{<!-- -->
    return number;
}

No object is defined, and static members can also be referenced through class names.

 cout << Box::GetNumber() << endl;
    //No object generated, number = 0;

Although static members do not belong to an object of the class, we can still use objects, references or pointers of the class to access static members.

int main()
{<!-- -->
    Box B1;
Box B2{<!-- --> 1,1,1};
    cout << B2.GetNumber() << endl;
    //Two objects are generated, number = 2;
return 0;
}

When defining static members outside a class, the static keyword cannot be repeated.