1.构造函数:(与类名相同,并且可以发生重载)
- 默认构造函数(无参):
- 有参构造函数(有参):
- 拷贝构造函数(参数为另一个对象):
2.析构函数:
注意:1.构造函数和析构函数必须写在public权限下面。
2.有默认值的构造函数不能再去创建无参的同名的构造函数
3.构造函数的调用方式:
1. 括号法调用
括号法调用
Person p1(1); //有参
p1.m_Age = 10;
Person p2(p1); //拷贝
cout << "p2的年龄" << p2.m_Age << endl;
Person p3; //默认构造函数 不要加() Person p3(); //编译器认为这行是函数的声明
//括号法调用就是调用有参构造函数和拷贝构造函数。如果想调用默认构造函数,什么都不要加。
2.显示法调用
Person p4 = Person(100);
Person p5 = Person(p4);
Person(100); //叫匿名对象 ,匿名对象特点,如果编译器发现了对象是匿名的,那么在这行代码结束后就释放这个对象,不用对象去接直接生成一个对象就是所谓的匿名对象。
不能用拷贝构造函数 初始化匿名对象
Person p6 = Person(p5); //如果写成左值,编译器认为你写成 Person p5; 对象的声明,如果写成右值,那么可以
3.隐式类型转换:
Person p7 = 100; //相当于调用了 Person p7 = Person(100) ,隐式类型转换
Person p8 = p7; // 相当于 Person p8 = Person(p7);
上面那种方式我觉得这种隐式类型转换只适用于属性只有一个这种情况。
并且g++ 编译器不允许person p7 = 100; 这种写法 。但是在vs环境中是可以的。第二种方式在g++ 和vs 两种环境都可以。
4.构造函数的调用规则:
1)当我们提供了有参构造函数,那么系统就不会在给我们提供默认构造函数了,但是 系统还会提供默认拷贝构造函数 , 进行简单的值拷贝;
2)当我们提供了 拷贝构造,那么系统就不会提供其他构造了;
3)简单的值拷贝,意思就是就是直接赋值,但是并不会考虑到内存相关的管理。
5.深拷贝和浅拷贝就是关于内存管理以及拷贝构造函数的相关的一些注意点:
深拷贝和浅拷贝主要原因是在于系统提供的默认拷贝函数是只提供了简单的值拷贝,并且如果我们的类里面 操作了一些我们申请的内存,就会出现深拷贝和浅拷贝的问题,形象的代码用C语言代码来示例更好:
class person
{
public:
person()
{
}
person(char *name1,int age)
{
this->name = (char *)malloc(strlen(name1)+1);
strcpy(this->name,name1);
this->age = age;
}
~person()
{
if(this->name != NULL)
{
free(this->name);
this->name = NULL;
}
}
int age;
char *name;
};
int main(void)
{
person p1("duqian",10);
person p2(p1);
return 0;
}
上述代码会出错,我们需要自己写一个拷贝构造函数来替代掉默认的拷贝构造函数:
class person
{
public:
person()
{
}
person(char *name1,int age)
{
this->name = (char *)malloc(strlen(name1)+1);
strcpy(this->name,name1);
this->age = age;
}
person(person &p)
{
this->age = p.age;
this->name = (char *)malloc(sizeof(p.name)+1);
strcpy(this->name,p.name);
}
~person()
{
if(this->name != NULL)
{
free(this->name);
this->name = NULL;
}
}
int age;
char *name;
};
int main(void)
{
person p1("duqian",10);
person p2(p1);
return 0;
}
上述就是深拷贝和浅拷贝。
6.explicit 关键字:
如果类的构造函数里面,提供了一个一个参数的构造函数(包括了默认参数的情况),那么是可以使用隐式类型转换的。加上explicit 关键字,则不支持隐式类型转换。
class person
{
public:
person()
{
}
//在这个构造函数前面加explicit ,则这个类就不支持隐式类型转换了.
person(int a)
{
this->age = a;
}
person(int a,int b)
{
this->age = a;
this->num = b;
}
person (person &p)
{
this->age = p.age;
this->num = p.num;
}
void func()
{
cout <<this->age<<endl;
}
int age;
int num;
};
int main(void)
{
//g++支持这样的方式
person p1(12,13);
p1 = 100;
// g++ 编译器不支持,vs编译器支持 person p1 = 100;
p1.func();
return 0;
}
7.初始化列表:
//主要是用来初始化数据的
//构造函数后面 + : 属性(参数), 属性(参数)...
person(int a,int b):age(a),num(b)
{
}