今日学习内容
一、C++中的this关键字
- this相当于一个const指针,指向当前使用的对象,通过this可以访问当前对象的所有成员。比如:shop.show();当前的对象就是shop,this就是指向shop。
- 用this访问成员变量或者成员函数时用“->”,例如:this->price; 。
- this 虽然用在类的内部,但是只有在对象被创建以后才会给 this 赋值,并且这个赋值的过程是编译器自动完成的,不需要用户干预,用户也不能显式地给 this 赋值。
- this 是 const 指针,它的值是不能被修改的,如赋值、递增、递减等都是不允许的。
- this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的。
- 只有当对象被创建后 this 才有意义,因此不能在 static 成员函数中使用。
二、this的本质
- this 实际上是成员函数的一个形参,在调用成员函数时将对象的地址作为实参传递给 this。不过 this 这个形参是隐式的,它并不出现在代码中,而是在编译阶段由编译器默默地将它添加到参数列表中。
- this 作为隐式形参,本质上是成员函数的局部变量,所以只能用在成员函数的内部,并且只有在通过对象调用成员函数时才给 this 赋值。
- 成员函数最终被编译成与对象无关的普通函数,除了成员变量,会丢失所有信息,所以编译时要在成员函数中添加一个额外的参数,把当前对象的首地址传入,以此来关联成员函数和成员变量。这个额外的参数,实际上就是 this,它是成员函数和成员变量关联的桥梁。
#include <iostream>
using namespace std;
class Paper{
public:
Paper(){
cout<<"调用顺序2"<<endl;
}
~Paper(){
cout<<"调用顺序5"<<endl;
}
};
class Book{
public:
Book(){ }
~Book(){ }
void setname(char *name);
void setprice(int price);
void show();
private:
char *m_name;
int m_price;
};
void Book::setname(char *name){
this->m_name = name;
}
void Book::setprice(int price){
this->m_price = price;
}
void Book::show()
{
cout<<this->m_name<<"售价为:"<<this->m_price<<endl;
}
int main()
{
Book newbook;
newbook.setname("巴黎圣母院");
newbook.setprice(45);
newbook.show();
return 0;
}
运行结果: 示例中的this就是指Book类中newbook对象。
三、C++中的static关键字
1.同一个类的不同的对象占用不同的内存,所以当修改一个对象的成员变量的值时,不会影响另一个对象的值。例如:Book类有有两个对象book1和book2,修改book1.price,并不会影响book2.price。 2.但有些场景需要在不同对象之间实现数据共享,比如book1和book2的price需要定为相同,这样修改一处即可改变。使用静态成员变量来实现多个对象共享数据的目标。 3.静态成员变量:被关键字static修饰。
#include<iostream>
using namespace std;
class Child{
public:
Child(char *name, int age);
void show();
static int getNum();
static int m_tatal;
private:
char *m_name;
int m_age;
};
int Child::m_tatal = 0;
Child::Child(char *name, int age):m_name(name), m_age(age){
m_tatal++;
}
void Child::show(){
cout<<m_name<<"的年龄是:"<<m_age<<"岁, ";
cout<<"这是第"<<m_tatal<<"位孩子。"<<endl;
}
int Child::getNum()
{
return m_tatal;
}
int main()
{
int num;
Child XM("小明",16);
XM.show();
Child XH("小华",18);
XH.show();
Child XJ("小军",13);
XJ.show();
XM.m_tatal = 4;
cout<<XM.m_tatal<<endl;
cout<<XH.m_tatal<<endl;
cout<<XJ.m_tatal<<endl;
Child::m_tatal = 10;
num = Child::getNum();
cout<<num<<endl;
}
运行结果: 注意: a.静态成员变量属于类,不属于某个具体的对象; b. 当创建多个对象,也只为静态成员变量分配一份内存,所有对象使用的都是这份内存中的数据。当某个对象修改了 它,也会影响到其他对象。 c.static 成员变量必须在类声明的外部初始化,在初始化时不能再加 static,但必须要有数据类型。初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化为 0。 d. 没有在类外初始化的 static 成员变量不能使用。因为static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。 e. static 成员变量既可以通过对象来访问,也可以通过类来访问。 f. static 成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问。 g.static 成员变量和普通的 static 变量类似,都在内存分区中的全局数据区分配内存。
- 静态成员函数:用static修饰的成员函数。
注意: a 普通成员函数可以访问所有成员(包括成员变量和成员函数),静态成员函数只能访问静态成员。 b. 与普通成员函数的区别: (1)普通成员函数只能在创建对象后通过对象来调用,因为它需要通过隐式的this获取当前对象的地址。但静态成员函数可以通过类来直接调用,编译器不会为它增加形参 this,它不需要当前对象的地址,所以不管有没有创建对象,都可以调用静态成员函数。 (2)普通成员变量占用对象的内存,静态成员函数没有 this 指针,不知道指向哪个对象,无法访问对象的成员变量,也就是说静态成员函数不能访问普通成员变量,只能访问静态成员变量。 (3)静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。 c. 在C++中,静态成员函数的主要目的是访问静态成员。 d. 和静态成员变量类似,静态成员函数在声明时要加 static,在定义时不能加 static。 e.静态成员函数可以通过类来调用(一般都是这样做),也可以通过对象来调用。
四、C++中的const关键字
在类中,如果不希望某些数据被修改,可以使用const关键字加以限定。const 可以用来修饰成员变量和成员函数。 1.const 成员变量 const 成员变量的用法和普通 const 变量的用法相似,只需要在声明时加上 const 关键字。初始化 const 成员变量只有一种方法,就是通过构造函数的初始化列表。
#include<iostream>
using namespace std;
class Time{
public:
Time(int Num);
void show();
private:
const int m_MonthNum;
};
Time::Time(int Num):m_MonthNum(Num){
cout<<"常数成员变量初始化完毕"<<endl;
}
void Time::show(){
cout<<m_MonthNum<<endl;
}
int main()
{
Time TimeOne(12);
TimeOne.show();
return 0;
}
- const成员函数
a. const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值。 b. 常成员函数需要在声明和定义的时候在函数头部的结尾加上 const 关键字,缺一不可。 c.常成员函数的作用主要是保护数据不被改写。
#include<iostream>
using namespace std;
class Stu{
public:
Stu(char *name, int age, int height);
char* getName() const;
int getAge() const;
int getHeight() const;
private:
char *m_name;
int m_age;
int m_height;
};
Stu::Stu(char *name, int age, int height):m_name(name),m_age(age),m_height(height){
cout<<"构造函数初始化完毕"<<endl;
}
char* Stu::getName() const
{
return m_name;
}
int Stu::getAge() const
{
return m_age;
}
int Stu::getHeight() const
{
return m_height;
}
int main()
{
char *name;
int age;
int height;
Stu LM("LiMing",18,165);
name = LM.getName();
age = LM.getAge();
height = LM.getHeight();
cout<<name<<"的年龄是:"<<age<<"他的身高是:"<<height<<endl;
int num;
cin>>num;
return 0;
}
运行结果: 通过这种const修饰的常成员函数来get某个变量的值,就是防止变量被改写。 3.const修饰函数时注意const放置的位置 a. 函数开头的 const 用来修饰函数的返回值,表示返回值是 const 类型,也就是不能被修改,例如const char * getname()。 b. 函数头部的结尾加上 const 表示常成员函数,这种函数只能读取成员变量的值,而不能修改成员变量的值,例如char * getname() const。
- const对象(常对象)
常对象:对象被const修饰。 常对象只能调用类的 const 成员(包括 const 成员变量和 const 成员函数)。
const class 对象名(参数);
class const 对象名(参数;
const class *p = new class(对象名);
class const *p = new class(对象名);
|