[C++从入门到精通] 9.inline、const、mutable、this和static

简介: [C++从入门到精通] 9.inline、const、mutable、this和static

一. 特殊的成员函数inline

假设我们不在头文件中声明、源文件中定义函数了,而是全部放在头文件中来实现:

class Time
{
public:
    explicit Time(int tmphour);  
  int Hour;
public:
  void addHour(int tempHour)
  {
        Hour += tempHour;
    } 
};

这种直接在类的定义中实现的函数,会被系统当做内联函数inline来处理,其他相关的知识点可以参考我们之前的讲解


二. 成员函数末尾的const

成员函数后面增加一个const的限定词后也被称为常量成员函数,其特性与用法如下:

特性:

1.不但要在成员函数的声明后增加const,也要在成员函数的定义中增加const
2.非成员函数不允许使用const修饰符
3.const成员函数既能被const类型对象调用也能被非const类型对象调用

作用:

const成员函数被限定:不能在函数中修改关于类的任何状态,包括其各种成员变量的值

举例:

//.h
class Time
{
public:
    explicit Time(int tmphour);  
    explicit Time();  
  int Hour;
public:
  void addHour(int tempHour) const;
};
//.cpp
void addHour(int tempHour) const
{
    Hour = tempHour;  //报错:表达式必须是可修改的左值(因为const定义的成员函数,其内的成员变量值不能被修改)
}

此外,const成员函数也是个万人迷,既能被const类型对象调用也能被非const类型对象调用;非const成员函数只能被非const类型对象调用。

public:
  void addHour(int tempHour) const;
  void addMinute(int tempMinute);


三. mutable

问题:

如何修改const修饰的常量成员函数中的成员变量?

前面我们说过常量成员函数中的成员变量不可以进行修改,这里有人会想了,那我直接取消常量成员函数后面的const修饰,将其变成普通成员函数,是不是就可以正常修改其内的成员变量了。没错,这样是可以修改了,但是我们不要忘了:

  • const成员函数既能被const类型对象调用也能被非const类型对象调用
  • const成员函数(普通成员函数)只能被非const类型对象调用

这就导致一个问题,就是如果之前代码中是使用const类型对象调用的常量成员函数,这时将常量成员函数变成普通成员函数后,我们也必须将调用其的const类型对象改为非const类型对象后才能正常调用修改后的普通成员函数。将原本const修饰的类对象取消掉,这违背了程序设计的初衷——不想让这个类对象修改成员变量的值。

定义:

为了解决上述的问题,我们引入了mutable的概念来突破const的限制,mutable(不稳定,容易改变的意思),const的反义词。

mutable修饰的成员变量,表示这个成员变量永远处于可以被修改的状态,即便是在const结尾的常量成员函数中。

举例:

class Time
{
public:
  mutable int Hour;
public:
  void addHour(int tempHour) const;
};
void Time::addHour(int tempHour) const
{
  Hour = tempHour;  //因为Hour是被mutable修饰的,这里即使是在常量成员函数addHour中,仍然可以被修改。
}

四. 返回自身对象的引用_this

class Time
{
public:
  int Hour = 50;
public:
  Time &addHour(int tempHour);
};
Time &Time::addHour(int tempHour)
{
  Hour += tempHour;
  return *this;  //把对象自己给返回去了
}
int main()
{
  Time myTime;
  myTime.addHour(2);
}

Time对象myTime的地址:0x001df720

返回的this指针地址仍为:0x001df720

结论: 说明this是一个指向自身类对象(myTime)的指针。

  • return *this返回的是当前对象的克隆或者本身(若返回类型为Time,则是克隆;若返回类型为Time&,则是本身。本文举例是后者)。
  • return this 返回当前对象的地址(指向当前对象的指针)

如何理解这个this?

当我们在程序中调用成员函数/成员变量时,编译器负责把这个对象的地址(&myTime)传递给成员函数中一个隐藏的this形参

即:

//我们写的:T
ime &Time::addHour(int tempHour){}
//实际上的
Time &Time::addHour(Time *this, int tempHour){}
Time myTime;
//我们写的:
myTime.addHour(2);  
//实际上的
myTime.addHour(&myTime, 2);  //调用时,编译器会把myTime的地址传递给成员函数隐藏的`this`形参

这也解释了一个问题:为什么在成员函数中,不需要调用就可以直接使用成员变量?

Time &Time::addHour(int tempHour)
{
    //程序员角度:
  Hour += tempHour;  //成员变量Hour 
  //系统的角度:
  this->Hour += tempHour;  
}

因为在系统角度看来,任何对类成员(Hour)的直接访问,都被系统看做是通过this做隐式调用的(this->Hour)。

this的相关特性:

  • this指针只能在成员函数中使用,静态函数或全局函数等是不存在this指针的。
  • 在普通成员函数中,this是一个指向非const对象的const指针。
    假设类是Time,那么this的实际定义是Time *const this,即this指针只能指向当前类对象,不能在指向其他类的对象(const后置)。
  • const成员函数中(void Time::addHour(int tempHour) const;), this是一个指向const对象的const指针。
    假设类是Time,那么this的实际定义是const Time *const this,不但this不能在指向其他类对象,而且this指向的自身类对象的成员变量值也不能更改。

五. static成员

参考我的另一篇文章:[C++] static静态成员变量/函数的用法


下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。


目录
相关文章
|
1月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
38 2
C++入门12——详解多态1
|
1月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
79 1
|
1月前
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
23 0
|
1月前
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
26 0
|
1月前
|
分布式计算 Java 编译器
【C++入门(下)】—— 我与C++的不解之缘(二)
【C++入门(下)】—— 我与C++的不解之缘(二)
|
1月前
|
编译器 Linux C语言
【C++入门(上)】—— 我与C++的不解之缘(一)
【C++入门(上)】—— 我与C++的不解之缘(一)
|
1月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
30 0
|
10天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
37 4
|
11天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
35 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4