C++入门之构造函数

目录

重载与引用

构造函数

实例化对象

析构函数

拷贝函数

other


重载与引用

重载,即函数名相同,调用不同的函数体

#include <iostream>

using namespace std;

int add(int a, int b)
{
	cout<<"add int+int"<<endl;
	return a+b;
}
#if 0 
double add(int a, int b) 
{
	cout<<"add int+int"<<endl;
	return a+b;
}
#endif
int add(int a, int b, int c)
{
	cout<<"add int+int+int"<<endl;
	return a+b+c;
}

double add(double a, double b)
{
	cout<<"add double+double"<<endl;
	return a+b;
}

double add(int  a, double b)
{
	cout<<"add int+double"<<endl;
	return (double)a+b;
}

double add(double a, int b)
{
	cout<<"add double+int"<<endl;
	return (double)a+b;
}

int main(int argc, char **argv)
{
	add(1, 2);
	add(1, 2, 3);
	add(1.0, 2.0);
	add(1, 2.0);
	add(1.0, 2);
	return 0;
}

对于重载,只能通过参数的不一样才能重载函数,不能通过返回类型的不一样重载函数,其DEMO运行结果如下

add int+int
add int+int+int
add double+double
add int+double
add double+int

与指针的区别,引用需要初始化,引用必须是变量,而不是一个值,例如"int a = 99; int &c = a;",在这里c相当于a的别名,共用一块内存

#include <iostream>

using namespace std;

int add_one(int a)
{
	a = a + 1;
	return a;
}

int add_one(int *a)
{
	*a = *a + 1;
	return *a;
}

int add_one_ref(int &b)
{
	b = b + 1;
	return b;
}

int main(int argc, char **argv)
{
	int a = 99;
	int &c = a; 
	cout<<add_one(a)<<endl;     //打印出返回值100
	cout<<"a = "<<a<<endl;      //a依然是99,因此打印出 a = 99

	cout<<add_one(&a)<<endl;    //传地址,通过指针寻址修改变量的值,打印出100
	cout<<"a = "<<a<<endl;      //a = 100

	cout<<add_one_ref(a)<<endl; //函数的形参 引用b与变量a共用内存,因此打印出101
	cout<<"a = "<<a<<endl;      //a = 101

	c++;                        //引用c与变量a共用内存,c加一相当于a的内容加一
	cout<<"a = "<<a<<endl;      //打印出a = 102
	cout<<"c = "<<c<<endl;      //打印出c = 102
	return 0;
}

DEMO运行结果如下

100
a = 99
100
a = 100
101
a = 101
a = 102
c = 102

 

构造函数

构造函数 ,是一种特殊的方法,主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中,特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们即构造函数的重载,在没写构造函数之前,在类中默认提供一个空的构造函数

#include <iostream>
using namespace std;

class Person {
private:
	char *name;
	int age;
	char *work;

public:

	Person() {cout <<"Pserson()"<<endl;}
	Person(char *name) 
	{
		cout <<"Pserson(char *)"<<endl;
		this->name = name;
	}

	Person(char *name, int age)
	{
		cout <<"Pserson(char*, int)"<<endl;
		this->name = name;
		this->age = age;
	}
	
	void setName(char *n)
	{
		name = n;
	}
	int setAge(int a)
	{
		if (a < 0 || a > 150)
		{
			age = 0;
			return -1;
		}
		age = a;
		return 0;
	}
	void printInfo(void)
	{
		cout<<"name = "<<name<<", age = "<<age<<", work = "<<work<<endl;
	}
};

int main(int argc, char **argv)
{
	Person per("zhangsan", 16);
	Person per2;

	per.printInfo();
	
	return 0;
}

打印结果如下,在main函数中添加"Person per3();",打印结果与下面一致,对于"Person per2;"来说会调用无参构造函数,而"Person per3();"不会调用,实质上是定义了一个函数,类似于"int fun();"

Pserson(char*, int)
Pserson()
name = zhangsan, age = 16, work = none

实例化对象

修改main函数,在C++中实例化一个对象与new运算符配合,在以下程序中如果没有delete,在程序结束后会自动释放,用delete可以实现手动释放

int main(int argc, char **argv)
{
	Person per("zhangsan", 16);
	Person per2;   /* 调用无参构造函数 */
	Person per3(); /* int fun(); */

	Person *per4 = new Person;
	Person *per5 = new Person();

	Person *per6 = new Person[2];

	Person *per7 = new Person("lisi", 18, "student");
	Person *per8 = new Person("wangwu", 18);

	per.printInfo();
	per7->printInfo();
	per8->printInfo();

	delete per4;
	delete per5;
	delete []per6;
	delete per7;
	delete per8;

	return 0;
}

修改构造函数,在构造函数中实现对name和work实现实例化,在程序结束后同样会释放构造函数中new的实例化,但delete不会释放构造函数中new的实例化,这样就会造成内存泄露

	Person(){cout<<"Person()"<<endl;
	}
	Person(char *name)
	{
		cout<<"Person(char *)"<<endl;
		this->name = new char[strlen(name) + 1];
		strcpy(this->name, name);
	}

	Person(char *name, int age, char *work = "none")//如果调用的话只传入两个参数,work就会被传入null
	{
		cout<<"Person(char *, int)"<<endl;
		this->name = new char[strlen(name) + 1];
		strcpy(this->name, name);
		
		this->age = age;
		
		this->work = new char[strlen(work) + 1];
		strcpy(this->work, work);
	}

为了证明上面会造成内存泄露,修改一下main函数,将实例化写成一个函数并且在main函数中调用多次

void test_fun()
{
	Person per("zhangsan", 16);
	Person per2;   /* 调用无参构造函数 */
	Person per3(); /* int fun(); */

	Person *per4 = new Person;
	Person *per5 = new Person();

	Person *per6 = new Person[2];

	Person *per7 = new Person("lisi", 18, "student");
	Person *per8 = new Person("wangwu", 18);

	per.printInfo();
	per7->printInfo();
	per8->printInfo();

	delete per4;
	delete per5;
	delete []per6;
	delete per7;
	delete per8;

}

int main(int argc, char **argv)
{
	for (int i = 0; i < 1000000; i++)
		test_fun();
	cout << "run test_fun end"<<endl;
	sleep(10);
	return 0;
}

 运行程序,通过free查看内存使用情况,在整个程序结束后才会释放构造函数中释放的new实例化

析构函数

在类中加入析构函数,实例化在delete才会调用析构函数,因此加入下面析构函数后,执行程序再通过free查看状态,可以看到不会内存泄露

	~Person()
	{
		if (this->name)
			delete this->name;
		if (this->work)
			delete this->work;
	}

修改main函数和test_fun函数,test_fun函数结束后,首先销毁的是lisi,然后才是zhangsan,因为"delete per7"在销毁的瞬间会先调用析构函数,若注释了"delete per7",在test_fun函数结束后,其析构函数不会被执行

void test_fun()
{
	Person per("zhangsan", 16);

	Person *per7 = new Person("lisi", 18, "student");
	delete per7;
}

int main(int argc, char **argv)
{
	test_fun();
	cout << "run test_fun end"<<endl;
	sleep(10);
	return 0;
}

打印结果

~Person()
name = lisi
work = student
~Person()
name = zhangsan
work = none
run test_fun end

注释了"delete per7"的结果如下:

~Person()
name = zhangsan
work = none
run test_fun end

拷贝函数

去掉test_fun函数,修改main函数如下,如果在Person中没有写拷贝函数,per2就会用per默认的拷贝函数,和per指向同一块内存,这样的话释放会执行两次,因此我们写出自己的拷贝函数

int main(int argc, char **argv)
{
	Person per("zhangsan", 18);
	Person per2(per);
	per2.printInfo();

	return 0;
}

在类中写出自己的拷贝函数

	Person(const Person &per) 
	{
		cout <<"Pserson(Person &)"<<endl;
		this->age = per.age;

		this->name = new char[strlen(per.name) + 1];
		strcpy(this->name, per.name);

		this->work = new char[strlen(per.work) + 1];
		strcpy(this->work, per.work);
	}

 

other

修改mian函数,全局对象和局部对象,先全局per_g被构造,后再到main函数中

Person per_g("per_g", 10);

void func()
{
	Person per_func("per_func", 11);
	static Person per_func_s("per_func_s", 11);
}

int main(int argc, char **argv)
{
	Person per_main("per_main", 11);
	static Person per_main_s("per_main_s", 11);

	for (int i = 0; i < 2; i++)
	{
		func();
		Person per_for("per_for", i);
	}

	return 0;
}

执行结果如下,其中per_func在执行完func函数后就会被销毁,然后静态变量不会

Pserson(char*, int), name = per_g, age= 10
Pserson(char*, int), name = per_main, age= 11
Pserson(char*, int), name = per_main_s, age= 11
Pserson(char*, int), name = per_func, age= 11
Pserson(char*, int), name = per_func_s, age= 11
~Person()
name = per_func
work = none
Pserson(char*, int), name = per_for, age= 0
~Person()
name = per_for
work = none
Pserson(char*, int), name = per_func, age= 11
~Person()
name = per_func
work = none
Pserson(char*, int), name = per_for, age= 1
~Person()
name = per_for
work = none
~Person()
name = per_main
work = none
~Person()
name = per_func_s
work = none
~Person()
name = per_main_s
work = none
~Person()
name = per_g
work = none

多一个Student类,在类中添加Person类,如果类里面带有参数的结构体函数,则系统就不会提供无参的构造函数,因此需要我们自己实现,因此我们需要提供无参构造函数,main函数中的构造Student对象,会先调用father和mother的构造函数,再调用自己的,对于析构函数则与构造函数调用的顺序相反,先调用Student的析构函数,在调用Person的析构函数

class Student {
private:
	Person father;
	Person mother;
	int student_id;
public:
	Student()
	{
		cout<<"Student()"<<endl;
	}

	Student(int id, char *father, char *mother, int father_age = 40, int mother_age = 39) : mother(mother, mother_age), father(father, father_age)
	{
		cout<<"Student(int id, char *father, char *mother, int father_age = 40, int mother_age = 39)"<<endl;
	}

	~Student()
	{
		cout<<"~Student()"<<endl;
	}

	
};

int main(int argc, char **argv)
{
	Student s(100, "bill", "lily");
	
	return 0;
}

执行结果如下

Pserson(char*, int), name = bill, age= 40
Pserson(char*, int), name = lily, age= 39
Student(int id, char *father, char *mother, int father_age = 40, int mother_age = 39)
~Student()
~Person()
name = lily
work = none
~Person()
name = bill
work = none

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值