C++知识点之成员函数中const的用法

 更新时间:2022年11月25日 09:40:57   作者:EJoft  
这篇文章主要介绍了C++知识点之成员函数中const的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

const 在C++中是一个很重要的关键字,其不光可以用来修饰变量,还可以放在函数定义中,这里整理了其在函数中的三个用法。

修饰入参

首先我们要明白在C++中调用函数时存在两种方法,即传递值和传递引用。

值传递

值传递时,调用函数时会创建入参的拷贝,函数中的操作不会对原值进行修改,因此这种方式中不需要使用 const 来修饰入参,因为其只是对拷贝的临时对象进行操作。

址传递

传递地址时函数中的操作实际上是直接对原来的值进行修改,因此我们这里可以使用 const 修饰入参。

const修饰入参

当const修饰函数入参时表示该参数不能被修改,这个是最好理解的,比如一个函数的功能是拷贝,那么入参中的源文件都会用 const 修饰。

void A::show(const int *b) {
    cout << "show const";
    //  error:  read-only variable is not assignable
    // *b = 2;
    cout << b << endl;
}

接下来我们要关注的是这里 const 对于函数重载的作用,这里给出结论,欢迎大家讨论,对应按值传递的函数来说 const 不会有重载的效果,但是传递指针和引用是会有重载的效果。

void A::show(const int b)
// void A::show(int b) // error class member cannot be redeclared
void display(int *num); // overload
void display(const int *num); // overload
void fun(A &a); // overload
void fun(const A &a); // overload

函数重载的关键是函数的参数列表——即函数特征标(function signature)。如果两个函数的参数数目和类型相同,并且参数的排列顺序也相同,则他们的特征标相同,而变量名是无关紧要的。

总结一下注意点:

  • 如果输入参数采用“值传递”,**由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加 const 修饰。**例如不要将函数 void Func1(int x) 写成 void Func1(const int x)。
  • 如果参数作为输出参数,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加 const 修饰,否则该参数将失去输出功能(因为有 const 修饰之后,不能改变他的值)。
  • 果参数作为输入参数,可以防止数据被改变,起到保护作用,增加程序的健壮性,建议是能加const尽量加上

上述测试代码如下:

#include <iostream>
using namespace std;
class A {
private:
    int a;
public:
    A(int a) {
        this->a = a;
    }

    void show(int b);
    // error redeclared
    // void show(const int b);
    void display(int *num); // ok
    void display(const int *num); // ok
    void fun(A &a);
    void fun(const A &a);
    void happy(int * h);
    void hour(const int * h);
};

void A::show(int b) {
    cout << "show: " << b << endl;
}

void A::display(int *num) {
    cout << "display:" << *num << endl;
}

void A::display(const int *num) {
    cout << "const display:" << *num << endl;
}

void A::fun(A &obj) {
    cout << "fun: " << obj.a << endl;
}

void A::fun(const A &obj) {
    cout << "const fun: " << obj.a << endl;
}

void A::happy(int *h) {
    cout << "happy:" << *h << endl;
}

void A::hour(const int *h) {
    cout << "const hour:" << *h << endl;
}

int main() {
    A a(1);
    const A a2(11);
    int b1 = 2;
    const int b2 = 3;
    // test overload
    a.show(b1);
    a.show(b2);
    a.display(&b1);
    a.display(&b2);
    a.fun(a);
    a.fun(a2);
    // test const
    a.happy(&b1);
    // a.happy(&b2); // error cannot initialize a parameter of type 'int *' with an rvalue of type 'const int *'
    a.hour(&b1);
    a.hour(&b2);
    return 0;
}

// ouptut
show: 2
show: 3
display:2
const display:3
fun: 1
const fun: 11
happy:2
const hour:2
const hour:3

修饰返回值

const 修饰返回值时,表示返回值不能被修改。

需要注意的是如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加 const 修饰没有任何价值。如果返回的是引用或指针,表示不能修改指向的数据。

一般用得多的是返回值是引用的函数, 可以肯定的是这个引用必然不是临时对象的引用, 因此一定是成员变量或者是函数参数, 所以在返回的时候为了避免其成为左值被修改,就需要加上const关键字来修饰。

我们可以看如下代码示例:

#include <iostream>

using namespace std;

class Alice {
private:
    int a;
public:
    Alice(int a): a(a) {}
    int get_a() {return a;}
    const int* get_const_ptr() {return &a;}
    int* get_ptr() {return &a;}
};

int main() {
    Alice alice(1);
    int a1 = alice.get_a(); // ok
    cout << a1 << endl;
    const int a2 = alice.get_a(); // ok
    cout << a2 << endl;

    // error cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'
    // int* b1 = alice.get_const_ptr();
    const int* b2 = alice.get_const_ptr(); // ok
    cout << *b2 << endl; // ok
    // *b2 = 3; // error read-only variable is not assignable

    *(alice.get_ptr()) = 3;
    cout << alice.get_a() << endl; // 3
    return 0;
}

修饰函数

const 也可以用来放在函数末尾,用来修饰成员函数,表明其是一个常成员函数,这个对于初次接触C++的同学来说会有点陌生,不过这也是C++中严谨的地方。

先看代码示例,学习任何编程技术都一定要写对应的代码,把它跑起来并分析结果才算是真正学会了,不会你只是知道了这个知识点,只知其然而不知其所以然。

纸上得来终觉浅,绝知此事要躬行,这里的要躬行指的就是写代码。

首先来看如下的代码

class Alice {
private:
    int a;
public:
    Alice(int a): a(a) {}
    void show();
};

void Alice::show() {
    cout << "hello Alice" << endl;
}

int main() {
    const Alice a(1);
    //  error: 'this' argument to member function 'show' has type 'const Alice', but function is not marked const
    // a.show();
    return 0;
}

上述代码会报错,因为 show() 方法不是常成员函数,而 a 是常对象。

本质上,成员函数中都有一个隐含的入参 this, 这个 this指的就是调用该方法的对象,而如果在函数的后面加上 const,那么这个 const 实际上修饰的就是这个 this。

也就是说函数后加上了 const,表明这个函数不会改变调用者对象。

这里借用侯捷老师的图片

上面图片表明,在正常情况下:

  • non-const对象可以调用const 或者 non-const 成员函数
  • const对象 只可以调用 const 成员函数

补充一点,**如果成员函数同时具有 const 和 non-const 两个版本的话, const 对象只能调用const成员函数, non-const 对象只能调用 non-const 成员函数。

**如以下代码示例

#include <iostream>
using namespace std;

class R {
public:
    R(int r1, int r2) {
        a = r1;
        b = r2;
    }

    void print();
    void print() const;

private:
    int a;
    int b;
};

void R::print() {
    cout << "normal print" << endl;
    cout << a << ", " << b << endl;
}

void R::print() const {
    cout << "const print" << endl;
    cout << a << ", " << b << endl;
}

int main() {
    R a(5, 3);
    a.print();
    const R b(6 ,6);
    b.print();
    return 0;
}
// output
normal print
5, 3
const print
6, 6

这里也是建议能加 const 的时候就加。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解Qt中线程的使用方法

    详解Qt中线程的使用方法

    这篇文章主要为大家详细介绍了Qt中线程的使用方法,文中的示例代码讲解详细,对我们学习Qt有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • C++使用OpenCV进行物体识别与检测的三种方法

    C++使用OpenCV进行物体识别与检测的三种方法

    物体识别与检测是计算机视觉中的核心任务之一,它被广泛应用于自动驾驶、安防监控、图像分析等领域,通过物体检测技术,计算机能够从图像中识别出特定的物体或目标,本文将介绍如何使用 C++ 和 OpenCV 库进行物体识别与检测,需要的朋友可以参考下
    2025-04-04
  • C++类的继承和派生及指针安全引用

    C++类的继承和派生及指针安全引用

    这篇文章主要介绍了C++类的继承和派生及指针安全引用,继承指从现有类获得其特性,派生指从已有类产生新的类,指针和引用并存,二者似乎有很多相同点,但是又不完全相同,下面关于两者的相关资料,需要的小伙伴可以参考一下
    2022-03-03
  • C语言实现通用数据结构之通用链表

    C语言实现通用数据结构之通用链表

    这篇文章主要为大家详细介绍了c语言实现通用数据结构之通用链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • C语言调用摄像头生成avi视频程序

    C语言调用摄像头生成avi视频程序

    这篇文章主要为大家详细介绍了C语言如何调用摄像头生成avi视频程序,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2023-11-11
  • C++11中std::move、std::forward、左右值引用、移动构造函数的测试问题

    C++11中std::move、std::forward、左右值引用、移动构造函数的测试问题

    这篇文章主要介绍了C++11中std::move、std::forward、左右值引用、移动构造函数的测试,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • C语言近万字为你讲透树与二叉树

    C语言近万字为你讲透树与二叉树

    树是计算机算法最重要的非线性结构。因为树能很好地描述结构的分支关系和层次特性,所以在计算机科学和计算机应用领域有着广泛的应用。这篇文章我就带大家一起了解一下树、二叉树这种结构,下篇文章会重点向大家介绍二叉树的遍历算法
    2022-05-05
  • C语言详细讲解多维数组与多维指针

    C语言详细讲解多维数组与多维指针

    C 语言中的多维数组(multidimensional array)其实就是元素为数组的数组。多维指针根据声明的维数需要进行多次地址转换才能够取到目标数据。但指针作为数据变量,可以多次赋值,使其成为对数组操作访问的一大利器,所以指针和数组的结合才是重中之重
    2022-04-04
  • ubuntu 下编译C++代码出现的问题解决

    ubuntu 下编译C++代码出现的问题解决

    这篇文章主要介绍了ubuntu 下编译C++代码出现的问题解决的相关资料,需要的朋友可以参考下
    2015-03-03
  • VS2022+libtorch+Cuda11.3安装测试教程详解(调用cuda)

    VS2022+libtorch+Cuda11.3安装测试教程详解(调用cuda)

    这篇文章主要介绍了VS2022+libtorch+Cuda11.3安装测试(调用cuda),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05

最新评论