C++-构造函数

C++提供了构造函数来处理对象的初始化。

构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行。

构造函数的名字与类名同名,以便编译系统识别;不具有任何类型,不返回任何值。

也可以在类内对构造函数进行声明,而在类外定义。

如果用户没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,也没有参数。

这个函数叫做默认构造函数

 

如果定义类的时候不给出构造函数和析构函数,那么C++编译器会自动生成一个无参构造函数、copy构造函数和一个析构函数。

如果定义了构造函数,那么C++编译器就不会生成无参构造函数,仍然会生成copy构造函数。

 

C++编译器提供的copy构造函数执行的是浅copy,如果需要执行深copy,需要自定义copy构造函数:

#include 
using namespace std;
#pragma warning (disable:4996)

class teacher {
public:
	teacher(int age, char *name) {
		this->age = age;
		this->name = (char *)malloc(20);
		strcpy(this->name, name);
	}
	~teacher() {
		free(this->name);
	}
public:
	void print() {
		cout << age << endl;
		cout << name << endl;
	}
private:
	char *name;
	int age;
};

void display_run(){// 显示对象的生命周期
	char s[] = "tom";
	teacher a(20, s);
	teacher b = a;
	a.print();
}

int main() {
	display_run();
	system("pause");

}

注:teacher b=a; 执行的是C++编译器提供的copy构造函数,只是复制指针变量的值,并不复制指针变量所指的内存空间,所以,b对象在free的时候会出现coredump。

此时,需要自定义copy构造函数,执行深copy。

有参数的构造函数,实参是在定义对象时给出的。

C++还提供另一种初始化数据成员的方法-参数初始化表 来实现对数据成员的初始化。

在一个类中可以定义多个构造函数,以便对类对象提供不同的初始化方法,这些构造函数具有相同的名字,而参数不同,这称为构造函数的重载。

构造函数初始化:

  1. 类名  对象(实参1,实参2....)     //point p1(1,2);
  2. 参数初始化表       //  void get_cube(int a,int b,int c):width(a),length(b),height(c){}

如果在一个类中定义全部默认参数的构造函数,不能再定义重载构造函数。//会产生二义性

C++编译器不能为某些类生成默认构造函数 (这个类包含一个其他类类型的成员且这个成员没有默认构造函数)

对象在以下情况下会发生拷贝:

  1. 初始化对象时 //调用构造函数     
  2. 以值的方式传递参数  //实参传递对象给形参
  3. 返回一个对象  //函数返回
#include 
using namespace std;

class point {
public:
	point(int x, int y) {
		this->x = x;
		this->y = y;
	}
	point(const point &p) {
		this->x = p.x;
		this->y = p.y;
	}
	~point() {
		cout << "析构" << endl;
	}
	
public:
	void getP() {
		cout << x;
	}
private:
	int x;
	int y;
};

void test(point p) {
	p.getP();
}

point test1() {
	point p1(4, 5);
	return p1;
}


int main() {
	point p(1, 2);
	point p1 = p; //第一种调用时机
	point p2(p);  //第一种调用时机 

	test(p); //第二种调用时机
	
	point p3 = test1(); //第三种调用时机  返回一个匿名对象,匿名对象转成p3
	
	point p4(1, 2);
	p4 = test1();  //第三种调用时机   返回一个匿名对象,匿名对象复制到p4,匿名对象被析构
	
	system("pause");
	
}

构造函数的初始化列表使用时机:

  1. 数据成员是const
  2. 数据成员是引用
  3. B类包含A类对象,并且A类不存在默认构造函数
#include 
using namespace std;

class A {
public:
	A(int a) {
		this->a = a;
	}
private:
	int a;
};

class B {
public:
	B(int b,int d):a(d)  {
		this->b = b;
	}
private:
	int b;
	A a;
};

int main() {
	B b1(1, 2);
	system("pause");
}

B类组合A类对象,先调用A类的构造函数,再调用B类的构造函数。析构的顺序与构造顺序相反。

如果有多个组合对象,调用构造函数的顺序按照定义顺序而不是根据初始化列表的顺序。

你可能感兴趣的:(C++,C,构造函数)