1.为什么要构造函数?
#include <stdio.h>
class Person {
private:
char *name;
int age;
char *work;
public:
void setName(char *name)
{
this->name = name;
}
int setAge(int age)
{
if (age < 0 || age > 150)
{
this->age = 0;
return -1;
}
this->age = age;
return 0;
}
void printInfo(void)
{
printf("name = %s, age = %d, work = %s\n", name, age, work);
}
};
int main(int argc, char **argv)
{
Person per;
//per.name = "zhangsan";
per.setName("zhangsan");
per.setAge(200);
per.printInfo();
return 0;
}
定义Person per后,要去设置Name、Age,调用两次函数效率低,因此有了构造函数
2.简介
构造函数就是和类名相同的函数,可以带参,也可以不带参
#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)
{
//printf("name = %s, age = %d, work = %s\n", name, age, work);
cout<<"name = "<<name<<", age = "<<age<<", work = "<<work<<endl;
}
};
int main(int argc, char **argv)
{
Person per("zhangsan", 16);
Person per2;
per.printInfo();
return 0;
}
C语言中 ( ) 一般对应函数的调用,定义了一个Person 类的对象,它会导致呢个函数被调用呢?
导致类里面相应构造函数被调用,
int main(int argc, char **argv)
{
Person per("zhangsan", 16); /* 调用两个参数的构造函数 */
Person per2; /* 调用无参的构造函数 */
Person per3(); /* int fun(); 只是一个函数声明,不会调用构造函数
相当于Person fun() */
per.printInfo();
return 0;
}
Person per2; /* 调用无参的构造函数 */
Person per3(); /* int fun(); 只是一个函数声明,不会调用构造函数Person fun() */
3.默认参数
上面的代码没有work,
a.可以实现带3个参数的构造函数, Person per("zhangsan", 16, "teacher"); 时调用
b.可以实现带2个参数的构造函数,把work指定为默认参数,Person per("zhangsan", 16); 时会调用,Person per("zhangsan", 16, "teacher"); 时也会调用
#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, char *work = "none") //默认参数char *work = "none"
{
cout <<"Pserson(char*, int)"<<endl;
this->name = name;
this->age = age;
this->work = work;
}
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)
{
//printf("name = %s, age = %d, work = %s\n", name, age, work);
cout<<"name = "<<name<<", age = "<<age<<", work = "<<work<<endl;
}
};
int main(int argc, char **argv)
{
Person per("zhangsan", 16); //没有传入work,默认为none
Person per2;
Person per3();
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;
}
4.实例化对象——用指针操作
Person *per4 = new Person;
Person *per5 = new Person();
//这两种方式的作用完全一样,都会调用Person类的无参构造函数来实例化对象
Person *per6 = new Person[2]; //数组 应该会调用两次无参构造函数?????
Person *per7 = new Person("lisi", 18, "student");//调用带2个参数的构造函数
Person *per8 = new Person("wangwu", 18); //work就是none,调用带2个参数的构造函数
//动态创建的对象怎么释放掉?
//程序执行完会自动释放
//手工释放,用delete
delete per4;
delete per5;
delete []per6; //对于数组
delete per7;
delete per8;
5.改进
前面的程序中,name和work都直接指向一个字符串,
修改一下构造函数,分配空间,保存这些变量
#include <iostream>
#include <string.h>
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 = new char[strlen(name) + 1];
strcpy(this->name, name);
}
Person(char *name, int age, char *work = "none")
{
cout <<"Pserson(char*, int)"<<endl;
this->age = age;
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
this->work = new char[strlen(work) + 1];
strcpy(this->work, work);
}
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)
{
//printf("name = %s, age = %d, work = %s\n", name, age, work);
cout<<"name = "<<name<<", age = "<<age<<", work = "<<work<<endl;
}
};
int main(int argc, char **argv)
{
Person per("zhangsan", 16);
Person per2;
Person per3();
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;
}
6.缺陷,引入析构函数
在构造函数中用new函数分配了堆空间,但是并没有释放
在main函数里面实例化对象,程序退出后,系统会帮助释放那些空间
但是如果是在子函数实例化对象呢?
把上面main函数代码放到一个测试函数里面
void test_fun()
{
Person per("zhangsan", 16);
Person per2;
Person per3();
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(); //执行1000000次,会消耗200M左右内存
cout << "run test_fun end"<<endl;
sleep(10);
return 0;
}
free -m 查看内存
a.执行前查看内存剩余2538M
b.执行完,打印"run test_fun end",内存剩余2356M
c.sleep(10); 内存自动恢复为2538M
说明:程序退出后,系统会帮助释放那些new函数分配的空间
但是在不断执行test_fun过程中,不断new分配的空间并没有释放
a.在test_fun中调用per7.freebuff(); per8.freebuff(); 不是一种好办法
void freebuff()
{
delete this->name;
delete this->work;
}
b.析构函数,做一些清除工作
~Person()
{
cout << "~Person()"<<endl;
if (this->name)
cout << "name = "<<name<<endl;
delete this->name;
if (this->work)
cout << "work = "<<work<<endl;
delete this->work;
}
这样,在休眠过程中也没有消耗过多的内存,不用等程序退出才释放内存
什么时候起作用?在实例化对象被销毁之前瞬间,系统帮助调用析构函数
有很多构造函数,只有一个析构函数,无参
7.实验a
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了
7.实验b
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 = zhangsan
work = none
run test_fun end
只执行了Zhangsan的析构函数,整个程序退出以后,lisi的析构函数也没有调用
表明:new函数分配的空间要用delete函数手动释放
如果没有手动释放,系统会帮助释放,但是不会调用析构函数
建议:new函数实例化对象要用delete函数手动释放