构造函数(constructor)是与类同名的特殊成员函数,主要用来初始化对象的数据成员。
像上一个例子,初始化的类成员的时候就有点麻烦。
class X{
...
X (...) {//构造函数
...
}
};
构造函数的特点:
#include <iostream>
using namespace std;
class Student{
private:
string m_name;
int m_age;
int m_no;
public:
Student(const string &name, int age, int no) {
m_name = name;
m_age = age;
m_no = no;
}
/*类内声明*/
void set_name(const string &name);
void set_age(int age);
void set_no(int no);
void eat(const string &food);
void who();
};
/*类外定义*/
void Student::set_name(const string &name){
m_name = name;
}
void Student::set_age(int age) {
m_age = age;
}
void Student::set_no(int no){
m_no = no;
}
void Student::eat(const string &food){
cout << "我今天吃了" << food << endl;
}
void Student::who() {
cout << "我叫: " << m_name << " 今年: " << m_age << " 学号: " << m_no << endl;
}
int main(void) {
Student s1("王钢蛋", 18, 2203);
s1.who();
s1.eat("烙饼");
return 0;
}
缺省构造函数也称无参构造函数,但其未必真的没有任何参数,为一个有参构造函数的每个参数都提供一个缺省值,同样可以达到无参构造函数的效果
注意:
#include <iostream>
using namespace std;
class A{
public:
int m_i;
A(void){
cout << "A 的无参构造" << endl;
m_i = 123;
}
};
class B{
public:
int m_j; //基本类型成员变量
A m_a; //类类型成员变量(成员子对象)
};
1
int main() {
B b; //调用成员对象m_a的无参构造函数 调用B的缺省构造函数
cout << b.m_j << endl; //未知
cout << b.m_a.m_i << endl; //123
return 0;
}
#include <iostream>
using namespace std;
struct param{
int l, w, h, ww;
};
class Desk{
public:
int length, width, height, weight;
Desk(int l, int w, int h, int ww) {
cout << "Desk(int,int,int,int)" << endl;
}
Desk(void) {
cout << "Desk(void)" << endl;
}
Desk(param &p){
cout << "Desk(param &)" << endl;
}
};
int main(void) {
Desk d1(1,2,3,4);
Desk d2;
param pm;
pm.l = 1;
pm.w = 2;
pm.h = 3;
pm.ww = 4;
Desk d3(pm);
return 0;
}
某些重载的构造函数具有特殊的含义:
将其他类型转换为当前类类型需要借助转换构造函数(Conversion constructor),转换构造函数只有一个参数。
#include <iostream>
#include <cstring>
using namespace std;
class Integer {
private:
int m_i;
public:
Integer(void){
cout << "Integer(void)" << endl;
m_i = 3;
}
explicit Integer(int n) {
cout << "Integer(int)" << endl;
m_i = n;
}
explicit Integer(const char *str){
cout << "Integer(const string &)" << endl;
m_i = strlen(str);
}
void print(){
cout << m_i << endl;
}
};
int main(void) {
Integer i;
i.print();
//Integer j = 5; //编译器会找参数为int类型的构造函数
Integer j = Integer(5); //编译器会找参数为int类型的构造函数
j.print();
//Integer k = "hello";
Integer k = Integer("hello");// 这样会更清晰调用的是那个构造函数
k.print();
return 0;
}
explicit关键字,就是告诉编译器需要类型转换时,强制要求写程如下形式:
Integer j = Integer(5);
//Integer j = 5; //error
用一个已定义的对象构造同类型的副本对象,将调用该类的拷贝构造函数
class A{
A(const A& that){ //拷贝构造函数 注意参数必须是常引用
...
}
};
A a;
A b(a);//调用拷贝构造
A c = a;//调用拷贝构造
案例:
#include <iostream>
using namespace std;
class Data{
public:
int m_data;
Data(int data = 3){
cout << "Data(int)" << endl;
m_data = data;
}
Data(const Data& that){ //拷贝构造函数
cout << "Data(const A&)" << endl;
m_data = that.m_data;
}
};
int main(void){
Data A1;
Data A2(A1); //编译器会调用拷贝构造函数
Data A3 = A1;
return 0;
}
如果一个类没有显示定义拷贝构造函数,那么编译器会为其提供一个缺省拷贝构造函数
class User {
string m_name; //调用string类的拷贝构造函数
int m_age; //按字节复制
};
案例:
#include <iostream>
using namespace std;
class A{
public:
int m_a;
A(int m_a = 0) { //缺省构造函数
cout << "A(int)" << endl;
}
A(const A& that){ //拷贝构造函数
cout << "A(const A&)" << endl;
}
};
class B{
public:
A m_b;
};
int main(void) {
B b1; //调用A类中的缺省构造函数
B b2 = b1; //默认调用A类中的拷贝构造函数
return 0;
}
注意事项