一、成员函数
可以在类里面定义,也可以在类外面定义。
class Student {
public:
string name;
int age;
char gender;
void show1() {
cout << "(" << name << ", " << age << ", " << gender << ")" << endl;
}
void show2();
};
void Student::show2() {
cout << "(" << name << ", " << age << ", " << gender << ")" << endl;
}
调用方式:
Student s1;
s1.name = "XX";
s1.show1();
二、构造函数(重点)
如果你在类里面不添加构造函数和析构函数,c++会给你默认添加3种函数,默认构造函数、拷贝构造函数和析构函数。
如果你添加了带参数的构造函数或拷贝构造函数,那么c++就不会给你自动添加默认构造函数,所以用的时候最好把默认构造函数也加上。
1、默认构造函数
class Student {
public:
int id;
Student() {
id = 0;
cout << "Student()" << endl;
}
};
2、带参数的构造函数
Student(int _id) {
id = _id;
cout << "Student(int _id)" << endl;
}
3、拷贝构造函数
Student(const Student& s) {
id = s.id;
cout << "Student(const Student & s)" << endl;
//前面加个const是为了避免拷贝进去之后被修改
}
4、构造函数的调用方法
Student s1;//默认
Student s2 = Student();//默认
Student s3 = {};//默认
Student s4(1);//带参数
Student s5 = Student(1);//带参数
Student s6 = { 1 };//带参数
Student s7(s1);//拷贝
Student s8 = Student(s1);//拷贝
Student s9 = { s1 };//拷贝
Student s10 = s1;//Student s10 = Student(s1);
下面的形式是错误的:
Student s1();//Declare a function
Student (s1);//不能单独把构造函数拿出来
三、析构函数(重点)
析构函数不接受参数。
class Student {
public:
int id;
Student() {
id = 0;
cout << "Student()" << endl;
}
~Student() {
cout << "~Student()" << endl;
}
};
int* test1() {
Student s = Student();
return &s.id;
}
如果main函数如下,则调用了析构函数:
void main() {
int* id = test1();//调用完该函数就出了作用域,析构
cout << *id << endl;//出错,已经被析构,访问不到
system("pause");
}
如果如下,则没有调用析构函数:
void main() {
Student s = Student();
system("pause");//;作用域在main函数内,pause暂停,未出作用域
}
再来看下面这个类:
class Teacher {
public:
int* age;
Teacher() {
age = new int(0);//堆区,需要手动删除
cout << "Teacher()" << endl;
}
~Teacher() {
//delete age;
cout << "~Teacher()" << endl;
}
};
int* test2() {
Teacher t = Teacher();
return t.age;
}
如果main函数如下,虽然析构了,但是没有删干净:
void main() {
int* age = test2();
cout << *age << endl;//所以这里依然访问的到
}
这里new应该跟delete配对。
四、浅拷贝/深拷贝(重点)
class Teacher {
public:
int* age;
Teacher() //默认构造函数
{
age = new int(0);
cout << "Teacher()" << endl;
}
~Teacher() {
delete age;
cout << "~Teacher()" << endl;
}
};
void test2() {
Teacher t1;
Teacher t2(t1);//浅拷贝
cout << *t1.age << endl;
cout << *t2.age << endl;//delete了两次,出错
}
深拷贝就能解决上面的问题,只是会多占一份内存。
深拷贝只需要在上面的代码基础上加一个拷贝构造函数,函数如下:
Teacher(const Teacher& t) //深拷贝
{
age = new int(*t.age);
cout << "Teacher(const Teacher & s)" << endl;
}
五、类的初始化
class Student {
public:
int id;
Student() : id(0) {}//默认
Student(int _id) : id(_id) {}//传参
Student(const Student& s) : id(s.id) {}//拷贝
};
六、类的成员是另一个类(小重点)
class Teacher1 {
public:
Student s;
};
void main() {
Student s;
Teacher1 t1(s);
}
构造时先构造里面的类(Student),再构造外面的类(Teacher1),析构时先析构外面的类,再析构里面的类。
七、this指针
class Student {
public:
int id;
Student(int id) {
this->id = id;
//id=id;//会报错
}
Student(const Student& s) //拷贝构造函数
{
id = s.id;
cout << "Student(const Student& s)" << endl;
}
Student& id_plus1(Student& s) {
id += s.id;
return *this;
}
Student* id_plus2(Student& s) {
id += s.id;
return this;
}
Student id_plus3(Student& s) //不考,只考前两个链式调用
{
id += s.id;
return *this;
}
};
void main() {
Student s1(18);
cout << s1.id << endl;//18
Student s2(18);
s2.id_plus1(s1).id_plus1(s1);//54,链式调用
//s2.id_plus2(s1)->id_plus2(s1);//54,链式调用
//s2.id_plus3(s1).id_plus3(s1);//调用拷贝构造函数,s2其实只加了一次,所以输出36
cout << s2.id << endl;
}
八、const关键字(不重点考察)
函数加const不能修改属性的值,但是加个mutable又可以修改(控制权限)。
class Student {
public:
int id;//不能修改
mutable int age;//可以修改
void modify1() const {
id = 100;
age = 18;
}
};