1.自定义命名空间
namespace tangsan {
int age = 20;
char * level = "唐三是封号斗罗";
void show() {
cout << "level:" << level << ", age:" << age << endl;
}
void doAction() {
cout << "唐三 在嘉陵关大战比比东" << endl;
}
}
//这样使用是全局属性 全局可用
using namespace tangsan;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//局部可用
using namespace tangsan;
show();
return a.exec();
}
使用命名空间可以直接调用命名空间内部的函数。
2.c++构造函数
class Student {
public:
Student() {
cout << "空参数构造函数" << endl;
}
// 先调用两个参数的,再调用一个的
Student(char *name) :Student(name, 87) {
cout << "一个参数的构造函数" << endl;
this->name = name;
}
// :name(name) 等价 this->name = name;
/*Student(char * name) :name(name) {
cout << "一个参数的构造函数" << endl;
}*/
// 两个参数的构造函数
Student(char *name, int age) {
//浅拷贝
// this->name = name;
// 堆区深拷贝
this->name = (char *) (malloc(sizeof(char *) * 10));
strcpy(this->name, name);
this->age = age;
cout << "两个参数的构造函数" << endl;
}
// 析构函数 Student对象的,Student对象被回收了,你做一些释放工作
// delete stu 的时候,我们的析构函数一定执行
// free不会执行析构函数,也意味着,你没法在析构函数里面,做释放工作, malloc也不会调用构造函数
~Student() {
cout << "析构函数" << endl;
// 必须释放 堆区开辟的成员
if (this->name) {
free(this->name);
this->name = nullptr; // 执行NULL的地址,避免出现悬空指针
}
}
- Student(char *name) :Student(name, 87):这样会先执行两个参数的构造方法,然后再执行一个参数的构造方法。
- this->name = name:表示数值的浅拷贝。
- this->name = (char *) (malloc(sizeof(char *) * 10)):表示数值的深拷贝,在堆区开辟的空间,需要手动释放。
- 通过malloc在堆区申请的内存,需要使用free来释放内存,通过new关键字申请的内存,需要使用delete来释放内存。free不会执行析构函数,也意味着,你没法在析构函数里面做释放工作, malloc也不会调用构造函数,所以可以直接使用free来释放。
- new/delete 是一套 会调用构造函数 与 析构函数
- malloc/free是一套 不调用构造函数 与 析构函数, C的范畴,不推荐但是也是可以使用。
3.拷贝构造函数
class Douluo{
// 私有属性
public:
char *name;
int level;
public:
Douluo() { cout << "空参数构造函数" << endl; }
// 两个参数的构造函数
Douluo(char *name, int level) : name(name), level(level) {
cout << "两个参数构造函数" << endl;
}
// ~Student(char * name) { } 这样写,就不是析构函数了
~Douluo(){
cout<<"析构函数"<<endl;
}
//拷贝构造函数 拷贝构造函数 就是传了一个 自身的常量引用
Douluo(const Douluo & douluo){ //常量引用:只读的,不让你修改
cout<<"拷贝构造函数"<<endl;
this->name=douluo.name;
this->level=douluo.level-10;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//在栈区申请的内存
Douluo douluo = { "唐三",100};
//将一个对象赋值给另外一个对象 会触发拷贝构造函数
Douluo douluo2=douluo; //会执行拷贝构造函数 需要自己去赋值,否则没数据
// Douluo douluo2; //会执行空参数构造函数
// douluo2=douluo; //这样不会执行拷贝构造函数 但是会默认赋值
//执行了拷贝构造函数 两个对象的地址不一样
cout << "main douluo=" << &douluo << endl;
cout << "main douluo2=" << &douluo2 << endl;
cout << "main douluo2=" << douluo2.name <<" level="<<douluo2.level<< endl;
Douluo *douluo3 =new Douluo("小舞",100);
Douluo *douluo4=douluo3; //指针指向同一个地址 一个改了,就同时改了,这里压根不会执行拷贝构造函数
douluo4->level=99; //“->”调用一级指针的成员
cout << "main douluo4=" << douluo4->name <<" level="<<douluo4->level<< endl;
cout << "main douluo3=" << douluo3->name <<" level="<<douluo3->level<< endl;
return a.exec();
}
-
自定义拷贝构造函数:只需要在空参构造函数的基础上,传入常量引用就可以了。添加const的意义是为了提升性能,否则传入参数会再拷贝一份,如果添加const就不会再进行拷贝了。
-
Douluo douluo2=douluo:这个操作会触发拷贝构造函数,需要自己去赋值,否则没数据。
-
Douluo douluo2 douluo2=douluo:但是先声明再赋值就不会触发构造函数,会自动赋值。
-
如果通过new的方式初始化的指针类型,是不会触发拷贝构造函数的。
-
“->”调用一级指针的成员