思维导图

关键字
1.this指针
1.1 什么是this指针?
this指针是一种特殊的指针,在类内指向当前类的外部对象。在类的成员函数中,可以使用this指针来访问当前对象的成员变量和成员函数。通过this指针,可以避免在成员函数中使用与参数名或局部变量同名的成员变量时产生歧义。在类的成员函数中,this指针始终指向调用该函数的对象。可以这样理解,this代指当前操作的对象。
下面这个程序就会发现,类内调用的this指针和对象的地址是一样的。
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
int age;
string name;
public:
Techer(int a,string n){
age = a;
name = n;
}
void print(){
cout << this << endl;
}
};
int main (){
Techer t1(45,"xiaowang");
t1.print();
cout << &t1 << endl;
return 0;
}

1.2 对象调用成员
成员:成员变量 和成员方法。
成员必须由对象调用。
下面这段代码,思考一下,之前我们在类内为什么能直接调用类内函数和类内变量,其实这都是编译器在帮助我们优化,原型是类内变量和类内方法前面加上this->。
cpp
class Techer{
private:
int age;
string name;
public:
Techer(int a,string n){
age = a;
name = n;
//this.age = a; //原型
//this.name = n; //原型
}
void print1(){
cout << age << endl;
//cout << this->age << endl; //原型
}
void print2(){
print1();
cout << name << endl;
//this->print1(); //原型
//cout << this->name << endl; //原型
}
};
1.3 成员变量与局部变量命名冲突问题
当我们成员变量和局部变量命名冲突的时候,这个时候编译器就不知道如何优化,这个时候就会发生错误。比如下面这样写:
cpp
class Techer{
private:
int age;
string name;
public:
Techer(int age,string name){
age = age; //二义性,此时编译器不知道如何处理
name = name;
}
void print(){
cout << age << " " << name << endl;
}
};
所以只要我们的代码没有二义性,就可以解决,这里有两种解决方法:
(1)在有明确是类内变量的前面加上this->明确告诉编译器类内变量。
cpp
class Techer{
private:
int age;
string name;
public:
Techer(int age,string name){
this->age = age; //二义性,此时编译器不知道如何处理
this->name = name;
}
void print(){
cout << age << " " << name << endl;
}
};
(2)构造初始化列表。
这个时候,编译器明确规定只能把()内的局部变量复制给外面的成员变量,消除二义性
cpp
class Techer{
private:
int age;
string name;
public:
Techer(int age,string name):age(age),name(name){
}
void print(){
cout << age << " " << name << endl;
}
};
1.4 链式调用
如果一个成员的返回值类型是当前类型应用,则这个这个函数支持链式调用,函数体重一定return *this。加引号就是直接修改当前对象,如果不加引号,就是返回新对象并把新对象拷贝为当前对象。
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
int age;
string name;
public:
//初始化构造函数
Techer(int a,string n){
age = a;
name = n;
}
//拷贝构造函数
Techer(Techer &t){
age = t.age;
name = t.name;
cout << "拷贝" << endl;
}
//获取当前年龄
int get_age(){
return age;
}
//年龄累加,返回当前对象
Techer& addage(int a){
age += a;
return *this;
}
//不加引用会多次拷贝
Techer addage2(int a){
age += a;
return *this;
}
};
int main (){
Techer t1(45,"xiaowang");
cout << t1.addage(1).addage(2).addage(3).addage(4).get_age() << endl;
cout << "################" << endl;
cout << t1.addage2(1).addage2(2).addage2(3).addage2(4).get_age() << endl;
return 0;
}

2.static关键字
2.1 静态局部变量
static 可以修饰局部变量,这样的局部变量就是静态局部变量。当函数第一次被调用 的时候,创建这个静态局部变量,函数执行完后不会销毁,下次使用函数直接使用该静态局部变量。
局部静态变量属于于函数,只有函数可以访问它,生命周期延长但是作用于还在函数内
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
int age;
string name;
public:
Techer(int age,string name):age(age),name(name){}
int add(){
static int a = 2;
return ++a;
}
};
int main (){
Techer t1(45,"xiaowang");
cout << t1.add() << endl;
cout << "################" << endl;
cout << t1.add() << endl;
//cout << a << endl; //局部静态变量属于于函数,只有函数可以访问它,生命周期延长但是作用于还在函数内
return 0;
}

2.2 静态成员变量
使用static修饰的成员变量被称为静态成员变量 ,非const的静态成员变量不能被初始化,只有"const static int a = 1"这样才能初始化,这就有一个问题,都常量化了我创建它有什么意义。这个时候就可以在类内声明,类外初始化。类似于C语言的全局变量。哪里都可以用,但是必须加上作用域限定符,让编译器明白,你调用的是哪个静态成员变量。这个时候你创建的静态成员变量,整个程序就这一个,不管你创建多少个对象,多个对象共用这个静态成员变量。
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
int age;
string name;
public:
Techer(int age,string name):age(age),name(name){}
//const static int a = 1; //常量化静态成员变量
static int a; //类内声明
int b = 1;
};
int Techer::a = 1; //类外初始化
int main (){
Techer t1(45,"xiaowang");
Techer t2(40,"zhangsan");
cout << t1.a++ << endl; //t1和t2一起公有的a
cout << t1.a++ << endl;
cout << t1.b++ << endl; //t1独有的b
cout << t1.b++ << endl;
cout << "################" << endl;
cout << t2.a++ << endl;
cout << t2.a++ << endl;
cout << t2.b++ << endl;
cout << t2.b++ << endl;
cout << "################" << endl;
cout << Techer::a << endl;
return 0;
}

2.3 静态成员函数
使用static修饰成员函数就是静态成员函数 ,静态成员函数简单来说就是可以脱离类单独使用,类似于静态成员变量,但是也必须添加**作用域限定符,**让编译器明白你调用的函数是那个类的。这个时候静态成员函数就相当于C语言中的函数一样使用.
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
int age;
string name;
public:
Techer(int age,string name):age(age),name(name){}
static int add(int a,int b){ //静态成员函数
return a + b;
}
};
int add(int a,int b){ //正常函数
return a + b;
}
int main (){
Techer t1(45,"xiaowang");
cout << t1.add(5,5) << endl;
cout << "################" << endl;
cout << Techer::add(4,5) << endl;
cout << "################" << endl;
cout << add(3,4) <<endl; //调用全局函数不用加作用域限定符,不过你也可以把函数放到一个namesapce名字空间里
return 0;
}
3.const关键字
3.1 const成员函数
使用const修饰成员函数,表示常成员函数,这样的函数无法修改成员变量值,不能调用其他非const修饰的成员变量函数。
只要不修改成员变量的成员函数都加上const修饰。
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
int age;
string name;
public:
Techer(int age,string name):age(age),name(name){}
int get_age()const{
return age;
}
string get_name()const{
return name;
}
void print()const{ //不能调用不是const修饰的函数
cout << get_age() << endl;
cout << get_name() << endl;
}
};
int main (){
Techer t1(45,"xiaowang");
t1.print();
return 0;
}
3.2 const对象
被const修饰的对象,即使成员变量放在公共区域,也不能被修改,也不能调用不是const修饰的成员函数。下面两种当时都可以定义一个const对象。
cpp
const Techer t1(32,"lisi");
Techer t1 const(32,"lisi");
3.3 const成员变量
const修饰的成员变量表示常成员变量,这样的成员变量不能被修改。只要一旦定义了这个const对象,就不能修改成员变量,初始化的时候是可以重新赋值的。
(1).声明的时候直接赋值:
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
const int age = 45;
const string name = "zhangsna";
public:
int get_age()const{
return age;
}
string get_name()const{
return name;
}
void print()const{
cout << get_age() << endl;
cout << get_name() << endl;
}
};
int main (){
Techer t1;
t1.print();
cout << t1.get_age() << endl;
return 0;
}
(2).构造初始化列表:
cpp
#include <iostream>
#include <string>
using namespace std;
class Techer{
private:
const int age = 45;
const string name = "zhangsna";
public:
Techer(int age,string name):age(age),name(name){}
int get_age()const{
return age;
}
string get_name()const{
return name;
}
void print()const{
cout << get_age() << endl;
cout << get_name() << endl;
}
};
int main (){
Techer t1(34,"zhangsan");
t1.print();
cout << t1.get_age() << endl;
return 0;
}