A constructor

constructor is a special kind of class member function that is executed when an object of that class is instantiated. Constructors are typically used to initialize member variables of the class to appropriate default values, or to allow the user to easily initialize those member variables to whatever values are desired.

Unlike normal functions, constructors have specific rules for how they must be named:
1) Constructors should always have the same name as the class (with the same capitalization)
2) Constructors have no return type (not even void)

A constructor that takes no parameters (or has all optional parameters) is called a default constructor.

Here is an example of a class that has a default constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Fraction
{
private :
     int m_nNumerator;
     int m_nDenominator;
 
public :
     Fraction() // default constructor
     {
          m_nNumerator = 0;
          m_nDenominator = 1;
     }
 
     int GetNumerator() { return m_nNumerator; }
     int GetDenominator() { return m_nDenominator; }
     double GetFraction() { return static_cast < double >(m_nNumerator) / m_nDenominator; }
};

This class was designed to hold a fractional value as an integer numerator and denominator. We have defined a default constructor named Fraction (the same as the class). When we create an instance of the Fraction class, this default constructor will be called immediately after memory is allocated, and our object will be initialized. For example, the following snippet:

1
2
Fraction cDefault; // calls Fraction() constructor
std::cout << cDefault.GetNumerator() << "/" << cDefault.GetDenominator() << std::endl;

produces the output:

0/1

Note that our numerator and denominator were initialized with the values we set in our default constructor! This is such a useful feature that almost every class includes a default constructor. Without a default constructor, the numerator and denominator would have garbage values until we explicitly assigned them reasonable values.

Constructors with parameters

While the default constructor is great for ensuring our classes are initialized with reasonable default values, often times we want instances of our class to have specific values. Fortunately, constructors can also be declared with parameters. Here is an example of a constructor that takes two integer parameters that are used to initialize the numerator and denominator:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <cassert>
class Fraction
{
private :
     int m_nNumerator;
     int m_nDenominator;
 
public :
     Fraction() // default constructor
     {
          m_nNumerator = 0;
          m_nDenominator = 1;
     }
 
     // Constructor with parameters
     Fraction( int nNumerator, int nDenominator=1)
     {
         assert (nDenominator != 0);
         m_nNumerator = nNumerator;
         m_nDenominator = nDenominator;
     }
 
     int GetNumerator() { return m_nNumerator; }
     int GetDenominator() { return m_nDenominator; }
     double GetFraction() { return static_cast < double >(m_nNumerator) / m_nDenominator; }
};

Note that we now have two constructors: a default constructor that will be called in the default case, and a second constructor that takes two parameters. These two constructors can coexist peacefully in the same class due to function overloading. In fact, you can define as many constructors as you want, so long as each has a unique signature (number and type of parameters).

So how do we use this constructor with parameters? It’s simple:

1
Fraction cFiveThirds(5, 3); // calls Fraction(int, int) constructor

This particular fraction will be initialized to the fraction 5/3!

Note that we have made use of a default value for the second parameter of the constructor with parameters, so the following is also legal:

1
Fraction Six(6); // calls Fraction(int, int) constructor

In this case, our default constructor is actually somewhat redundant. We could simplify this class as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <cassert>
class Fraction
{
private :
     int m_nNumerator;
     int m_nDenominator;
 
public :
     // Default constructor
     Fraction( int nNumerator=0, int nDenominator=1)
     {
         assert (nDenominator != 0);
         m_nNumerator = nNumerator;
         m_nDenominator = nDenominator;
     }
 
     int GetNumerator() { return m_nNumerator; }
     int GetDenominator() { return m_nDenominator; }
     double GetFraction() { return static_cast < double >(m_nNumerator) / m_nDenominator; }
};

This constructor has been defined in a way that allows it to serve as both a default and a non-default constructor!

1
2
3
Fraction cDefault; // will call Fraction(0, 1)
Fraction cSix(6); // will call Fraction(6, 1)
Fraction cFiveThirds(5,3); // will call Fraction(5,3)

Classes without default constructors

What happens if we do not declare a default constructor and then instantiate our class? The answer is that C++ will allocate space for our class instance, but will not initialize the members of the class (similar to what happens when you declare an int, double, or other basic data type). For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Date
{
private :
     int m_nMonth;
     int m_nDay;
     int m_nYear;
};
 
int main()
{
     Date cDate;
     // cDate's member variables now contain garbage
     // Who knows what date we'll get?
 
     return 0;
}

In the above example, because we declared a Date object, but there is no default constructor, m_nMonth, m_nDay, and m_nYear were never initialized. Consequently, they will hold garbage values. Generally speaking, this is why providing a default constructor is almost always a good idea:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Date
{
private :
     int m_nMonth;
     int m_nDay;
     int m_nYear;
 
public :
     Date( int nMonth=1, int nDay=1, int nYear=1970)
     {
         m_nMonth = nMonth;
         m_nDay = nDay;
         m_nYear = nYear;
     }
};
 
int main()
{
     Date cDate; // cDate is initialized to Jan 1st, 1970 instead of garbage
 
     Date cToday(9, 5, 2007); // cToday is initialized to Sept 5th, 2007
 
     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值