1.类的构造函数
class Test
{
public:
//无参构造函数
Test()
{
cout << "无参构造函数" << endl;
}
//有参构造函数
Test(int a,int b)
{
cout << "有参构造函数" << endl;
}
//赋值或者拷贝构造函数
Test(const Test & t)
{
cout << "赋值或者拷贝构造函数" << endl;
}
private:
};
void main()
{
Test t;//这里调用了无参构造
Test t2(1,2);//这里调用有参构造函数
Test t3=Test(1, 2);
//这里也调用有参构造函数,相当于先创建一个匿名对象,然后在转成t3;也就是t3对象初始化
t = t3;//这个调用了t的拷贝构造函数;
system("pause");
}
初始化尽量放在构造函数中,有些情况就没有机会初始化了;
2.拷贝构造函数的几种调用场景
class Test
{
public:
int a;
//无参构造函数
Test()
{
cout << "无参构造函数" << endl;
}
//有参构造函数
Test(int a,int b)
{
cout << "有参构造函数" << endl;
}
//赋值或者拷贝构造函数
Test(const Test & t)
{
cout << "赋值或者拷贝构造函数" << endl;
}
~Test()
{
cout << "调用了析构函数" << endl;
}
void setObjiect(Test tt)
{
}
private:
};
Test getObject()
{
Test t;
t.a = 10;
return t;//在这里创建了一个匿名对象返回去,使用已有对象创出化匿名对象,调用匿名对象的拷贝构造函数
//在调用了t的析构函数,把匿名对象返回去,如果发现返回去没有人接受,所以把匿名对象也析构了,调用析构函数;
}
void main(){
Test t;//这里调用了无参构造
//Test t2(1,2);//这里调用有参构造函数
Test t3=Test(1, 2);
//这里也调用有参构造函数,相当于先创建一个匿名对象,然后在转成t3;也就是t3对象初始化
//第一种情况:调用了t的拷贝构造函数;用已有对象去初始化一个未有的对象;
Test t4 = t3;
//爹二种调用时机;
Test t5(t3);
//第三种调用时机,形参调用了拷贝构造函数;实参和形参就是两个不同的对象了
t5.setObjiect(t3);
//第四种调用时机,函数返回对象的时候
Test t6 = getObject();//如果有人接的话,就直接转成t6,不会调用t6的拷贝构造函数;
cout << "t6a:" << t6.a << endl;
Test t7;
t7.a = 100;
t7 = getObject();//如果用一个已经有的对象去接受的话,匿名对象会被析构掉的;t7已经不是之前的t7了
cout << "t7.a:" << t6.a << endl;
system("pause");
}
3.拷贝构造函数引发的“血案”
class Test
{
public:
int a=5;
char * name=NULL;
//无参构造函数
Test()
{
a = 10;
name =(char*) malloc(24);
strcpy(name,"abcdefg");
cout << "无参构造函数" << endl;
}
//有参构造函数
Test(int a,int b)
{
cout << "有参构造函数" << endl;
}
//赋值或者拷贝构造函数
Test(const Test & t)
{
}
~Test()
{
cout << "调用了析构函数" << endl;
}
void setObjiect(Test tt)
{
}
private:
};
void main(){
Test t1;
//Test t2 = t1;//调用t2的拷贝构造函数,但是t2对象中的成员变量还是类的原始数据;
//例如:类中的指针指向的是空,在构造函数中给申请了内存,但是在拷贝构造函数中没有申请内存,当你调用拷贝构造的时候那个指针还是NULL;
//就相当于对象重新创建只不过调用的是拷贝构造函数
Test t2;
t2 = t1;//这种操作字面上就是赋值,不会调用任何构造函数,变量的值都是相同的,从t1复制到t2,但是变量的内存地址是不同的;
//对于指针的话就是指针本身的地址是不同的,但是指针指向的内存空间的地址是相同的。这里就存在内存释放的时候会重复释放的问题。
//如果t1和t2都给指针分配了内存,当执行t2=t1的时候,t2中之前分配的内存就泄露了;
//这里需要重载=操作符;
cout << t1.a<<"----"<< t2.a << endl;
printf("指针的地址%d %d\n", &(t1.name), &(t2.name));
printf("a的地址%d %d\n", &(t1.a), &(t2.a));
cout << t1.name << "----" << t2.name << endl;
system("pause");
}
4.构造函数的初始化列表
class Teacher
{
public:
Teacher(int m,int n)
{
cout << "Teacher有参构造函数" << endl;
}
~Teacher()
{
cout << "Teacher调用了析构函数" << endl;
}
private:
};
class Test
{
public:
int a;
int b;
Teacher t1;
Teacher t2;
const int c;
//无参构造函数
Test():t1(1,2),t2(1,2),c(5)
{
cout << "Test无参构造函数" << endl;
}
//有参构造函数
Test(int a,int b) :t1(1, 2), t2(1, 2), c(5)
{
cout << "Test有参构造函数" << endl;
}
//有参构造函数
Test(int a, int b,int m,int n) :t1(m, n), t2(m, n), c(5)
{
cout << "Test有参构造函数" << endl;
}
//赋值或者拷贝构造函数
Test(const Test & t) :t1(1, 2), t2(1, 2), c(5)
{
}
~Test()
{
cout << "Test调用了析构函数" << endl;
}
private:
};
void main(){
//因为在Test类中存在,别的类的变量,所以在初始化Test的时候也要初始化别的类.
//初始化内部变量对象,必须通过外部对象的构造函数初始化,语法:Test():t1(1,2),t2(1,2) 外部构造方法:内部构造方法
//构造函数的执行顺序,先执行被走合函数的构造函数
//类种如果有const修饰的变量,也必须在构造函数的后面:初始化;
Test t;
Test t2(1,2,2,3);
system("pause");
}
构造函数的执行顺序:
先初始化的后析构,后初始化的先析构
5.在构造函数中再次调用构造函数的话,会会产生一个匿名对象,就是两个对象了,但是匿名对象在被调用的构造函数结束的时候会被析构掉;
6.C++中动态分配和释放内存,new和delete关键字:
class Teacher
{
public:
Teacher()
{
cout << "构造方法" << endl;
}
Teacher(int a)
{
cout << "有参构造方法" << endl;
}
~Teacher()
{
cout << "析构方法" << endl;
}
};
//new 和delete是C++的关键字
//new 基础变量类型 分配数组变量 分配类对象
void main(){
//在c语言中
int * p=(int *)malloc(sizeof(int));
*p = 100;
free(p);//delete(p); 这两种释放都是可以的
//在C++中
int* p1 = new int;//分配内存不初始话的;
*p1 = 100;
delete(p1);//free(p1); 这两种释放都是可以的
int* p2 = new int(100);//分配内存和初始话;
delete(p2);//free(p2); 这两种释放都是可以的
//在c语言中分配数组
int * arr = (int *)malloc(sizeof(int) * 10);
arr[0] = 100;
free(arr);//delete[] arr;这两种释放都是可以的
//在C++中分配数组
int* array = new int[10];
array[1] = 100;
delete(array);//free[] array;这两种释放都是可以的
//在c中,在分配内存中不会调用对象构造和析构方法
Teacher* t = (Teacher*)malloc(sizeof(Teacher));
free(t);//delete(t);释放内存了,但是会调用析构方法;
//在C++中
Teacher* t2 = new Teacher(10);//调用构造方法
delete t2;//调用析构函数;
//free(t2);//这样也释放内存了,但是不会调用析构函数的;
//总结,在使用new和delete的时候还是成对的去使用;malloc和free是成对的使用
system("pause");
}
7.静态成员变量和静态成员函数
静态是是属于类的,对象共用的;基本用法和java的静态是一样的,在C++中 通过类名调用有点区别:类名::静态成员或者方法
8.this指针
class Teacher
{
public:
int a;
Teacher(int a)//==>在c++编译器底层是这样做的Teacher(Teacher * this,int a)
{
this->a = a;
}
};
void main(){
Teacher t(5);//这边调用是t(&t,5);对象取地址传给方法的;
//这就是类的存放代码区,对象存在很多个的时候,调用同一份方法的时候会传对象过去的;也就是我们认为的找到对象自己的函数;
system("pause");
}