首页 > 编程笔记

C++类的构造函数(入门必读)

在 C++ 中,构造函数是特殊的成员函数,只要创建类对象,就必须调用构造函数。

构造函数的工作是保证每个对象的数据成员具有合适的初始值,本节重点介绍怎么定义和使用构造函数。

构造函数的定义

对于一个整型的变量,在定义的时候可以同时赋一个初值,例如:
int a = 1;
但是对于类对象,比如前面定义的类 Employee,如果想要在定义类对象的时候赋初值,比如:
Employee emp={"Jason", 8, 7000};
上面例子是想在定义的时候,让 emp 对象的数据成员分别为 Jason、8 和 7000,其实这是不可以的,类对象不可以直接这么赋初值。要想让类对象在生成的时候有一个初值,就要使用构造函数。

和类中其它的成员函数不同,构造函数和类同名,而且没有返回值类型。和其它成员函数相同的是,构造函数也有形参表和函数体。一个类可以有多个构造函数,每个构造函数必须有与其他构造函数不同数目或类型的形参。

例如,为 Employee 类添加构造函数:
// 定义 Employee类
class Employee {
public:
    //定义构造函数
    Employee(const char* n, int a, double s) {
        name = n;
        age = a;
        salary = s;
    }

private:
    const char * name;
    int age;
    double salary;
};

注意,构造函数也受 public、protected 和 private 访问限制的约束。

在上面的定义中增加了构造函数,本构造函数接收 3 个参数。有了这个定义之后,就可以在定义类对象的时候赋初值了,例如:
Employee emp("zhangsan", 10, 7000);
在创建对象的时候,编译器会自动调用构造函数,不需要程序员手动调用。

构造函数的重载

一个类可以包含多个构造函数,数量没有限制。不同的构造函数允许用户指定不同的方法来初始化类。和函数的重载一样,这些构造函数的形参必须不同。

当一个类定义了多个构造函数的时候,编译器会根据提供的实参的类型和数目来选择构造函数。

下面为 Employee 类增加不同的构造函数:
class Employee {
public:
    //定义构造函数
    Employee(); // ①
    Employee(const char* n); // ②
    Employee(const char* n, int a, double s); // ③
};
Employee emp1; // 调用构造函数 ①
Employee emp2("zhangsan"); // 调用构造函数 ②
Employee emp3("zhangsan", 10, 7000); // 调用构造函数 ③

默认构造函数

如果一个类的内部没有添加任何构造函数,那么创建类对象的时候会调用默认构造函数。

默认构造函数可以手动添加,也可以由编译器自动生成,为所有的数据成员提供初始化。默认构造函数没有任何参数,例如上边实例中Employee();就是默认构造函数。

注意,当为类手动添加了构造函数的时候,比如:
class myClass
{
public:
    myClass(int n);   
}
因为该类定义了构造函数,所以编译器不再为其添加默认构造函数,那么这个类就没有无参数的构造函数。因此构造这个类的对象的时候必须提供参数,也就是说下面的语句是错误的:
myClass my; // 错误,该类没有默认构造函数
上面的语句是错误的,因为编译器找不到无参数的构造函数定义,正确的方法就是提供一个初始参数:
myClass my(1);

复制构造函数

上文介绍了类的构造函数,可以方便地为类指定初始值,下面考虑用一个现有的类对象来创建新的对象的过程。

对于 C++ 内部数据类型,这个过程很容易理解,例如:
int a = 100;
int b = a;
类对象也可以像上面那样创建,例如:
Employee emp1;
Employee emp2 = emp1;
新生成的 emp2 所有的数据都和 emp1 一样,创建 emp2 对象的过程就调用了类中的复制构造函数,也叫拷贝构造函数。

复制构造函数是一个特殊的构造函数,该构造函数接收一个本类类型的引用作为参数,参数数目只能是一个。通过使用复制构造函数,可以用一个现有的类对象来创建一个新的类对象。

下面为 Employee 类添加一个复制构造函数:
class Employee {
public:
    //定义复制构造函数
    Employee(const Employee& e);
};

再次强调,复制构造函数的参数必须使用引用。

有了上面的定义之后,用 emp1 来创建 emp2 的时候,就会调用这个复制构造函数,并且把 emp1 作为参数传入。

同构造函数一样,如果一个类没有定义复制构造函数,编译器会自动添加一个复制构造函数;反之如果类中已经包含复制构造函数,那么编译器就不添加了。

一个类只能有一个复制构造函数。调用复制构造函数创建类对象,常见的场景有以下几个:

总结

在 C++ 中,构造函数起着至关重要的作用,确保对象在创建时具有合适的初始值。构造函数不仅可以通过参数传递进行定制化初始化,还可以通过多个重载版本以适应不同的初始化需求。

默认构造函数没有任何参数,可以手动定义,也可以由编译器自动添加。但一旦手动定义了任何类型的构造函数,编译器将不再添加默认构造函数。

复制构造函数用于创建一个新对象,并将现有对象的所有属性复制到新对象中,在函数参数传递和返回值等场景中特别有用。

推荐阅读