修饰 C++ 成员函数的两种关键字总结

修饰 C++ 成员函数的两种关键字总结

常量成员函数 (const 关键字)

const 修饰成员函数表示这个成员函数不能修改类的成员变量,因此这种成员函数称为常量成员函数。这样,编译器可以对这个函数进行深度的优化。另外,一个类的常量型示例只能调用常量型成员函数。比如下面这个例子。

class Test
{
public:
    Test();
    int getValue() const;
    int value();
private:
    int intValue;
};
Test::Test():
intValue(1)
{
}
int Test::getValue() const
{
    return intValue;
}

int Test::value()
{
    return intValue;
}

类 Test 有 getValue() 和 value() 两个成员函数,其中一个是常量型的。那么下面的代码中:

int main()
{
    Test A;
    const Test B;
    cout << A.getValue() << endl;
    cout << A.value() << endl;

    cout << A.getValue() << endl;
    cout << B.value() << endl;

    return 0;
}

B.value() 的访问就是非法的,因为 B 是常量,只能访问常量型成员函数。

作为一种良好的习惯,我们应该将类中所有不修改成员变量的函数都设为 const 型。

不过 const 型成员函数并非绝对不会改变类的成员。比如下面的代码:

#include <iostream>
using namespace std;
char STRING[] = "A STRING!";
class Test
{
public:
    Test();
    char * changeStr() const;

private:
    char *str;
};
Test::Test():
  str(STRING)
{
}

char * Test::changeStr() const
{
    str[1] = ‘x‘;
    return str;
}

int main()
{
    const Test A;
    cout <<  A.changeStr();

    return 0;
}

const 修饰符只能保证指针 str 指向的地址不被修改。而指向的字符串的值是可以随便改的。 如果将 str 从 char * 类型改为数组就不一样了。下面的代码无法编译。因为 str[1] = ‘x’ 这个操作是非法的。

#include <iostream>

using namespace std;

class Test
{
public:
    Test();
    char * changeStr() const ;

private:
    char str[10];
};
Test::Test()
{
    strcpy(str, "A STRING!");
}

char * Test::changeStr() const
{
    str[1] = ‘x‘;
    return str;
}

int main()
{
    Test A;
    cout <<  A.changeStr();

    return 0;
}

volatile 成员函数

与 const 相反,volatile 表示这个函数里访问的变量可能由于其他原因发生改变。比如其他线程可能会对这些变量赋值,或者硬件会有写其他的机制改变这些变量的值。这时这样的函数就应该用 volatile 关键字修饰,相当于告诉编译器,这个函数里访问的变量的值随时都可能变化,所以不要做访问优化。下面是个例子,A 被定义为 volatile 型变量,A.value() 必须要定义为 volatile,否则不能访问。

#include <iostream>

using namespace std;

class Test
{
public:
    Test();
    int value() volatile;

private:
    int v;
};
Test::Test()
{
    v = 1;
}

int Test::value() volatile
{
    return v;
}

int main()
{
    volatile Test A;
    cout <<  A.value() << endl;

    return 0;
}

volatile 和 const 也可以同时修饰一个函数。表示这个函数本身不修改变量的值,但是变量的值可能会自己变化。下面是例子:

#include <iostream>

using namespace std;

class Test
{
public:
    Test();
    int value() volatile const;

private:
    int v;
};
Test::Test()
{
    v = 1;
}

int Test::value() volatile const
{
    return v;
}

int main()
{
    volatile const Test A;
    cout <<  A.value() << endl;

    return 0;
}
时间: 2024-11-03 22:45:54

修饰 C++ 成员函数的两种关键字总结的相关文章

注册JNI函数的两种方式

前言 前面介绍过如何实现在Android Studio中制作我们自己的so库,相信大家看过之后基本清楚如何在Android studio创建JNI函数并最终编译成不同cpu架构的so库,但那篇文章介绍注册JNI函数的方法(静态方法)存在一些弊端,本篇将介绍另外一种方法(动态注册)来克服这些弊端. 注册JNI函数的两种方法 静态方法 这种方法我们比较常见,但比较麻烦,大致流程如下: - 先创建Java类,声明Native方法,编译成.class文件. - 使用Javah命令生成C/C++的头文件,

Button的Click事件与js函数的两种不同顺序触发方式

先执行js,或者先执行Click事件,最近就遇到了这个问题,开始弄了两个按钮分别执行,那才叫一个蛋疼... 1.先执行js,再执行Button的Click函数 <asp:Button ID="btn_delete" runat="server" Text="提交" onclick="button1_Click"/> 前台js为 <script language="javascript"&g

JavaScript中的函数的两种定义方式

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> /*I总结: 1.函数名可以做变量使用,可以赋值,可以传值 2.函数名当参数,传递给另一个函数 */ //==================js中函

strcmp函数的两种实现

strcmp函数的两种实现,gcc测试通过. 一种实现: C代码   #include<stdio.h> int strcmp(const char *str1,const char *str2) { /* 注释以下的五行(while循环)可以简写为: * for(;(*str1==*str2)&&*str1!='\0';str1++,str2++); *  */ while((*str1==*str2)&&*str1!='\0') { str1++; str2

override final default delete修饰的成员函数

1. override 重载 当你在父类中使用了虚函数时候,你可能需要在某个子类中对这个虚函数进行重写,以下方法都可以: class A { virtual void foo(); } class B :public A { void foo(); //OK virtual foo(); // OK void foo() override; //OK } 如果不使用override,当你手一抖,将foo()写成了f00()会怎么样呢?结果是编译器并不会报错,因为它并不知道你的目的是重写虚函数,而

getline()函数的两种用法

getline()函数的输入流对象可以是标准输入流对象cin,也可以是一个文件输入流对象fin; (1)输入流对象的成员函数(有三个参数,一般除非需要自己选定停止符,并不推荐使用): basic_istream<char>& istream::getline(char *str, streamsize num, char delim = '\n'); 这个函数是成员函数,所以必须通过对象调用.streamsize为signed integer type,其中: str为C 字符数组的首

虚函数的两种特性

在MFC编程中遇到了两种虚函数的特性,看如下代码,B继承于A,C继承于B,D继承于C,E继承于D,F继承于E. 第一种特性: #include <iostream> using namespace std; class A { public: virtual void vFunc(); }; class B:public A { public: virtual void vFunc(); }; class C: public B { public: virtual void vFunc();

函数——函数的两种声明方式:函数声明&amp;函数表达式的区别(未完待续。。。)

一.函数声明中函数名是必须的:函数表达式中则是可选的 //函数声明 function sum(a, b) { return a + b; } alert(sum(1, 2)); //函数表达式 /* var s = function sum(a, b) { return a + b; } alert(s(1, 2)); */ var s = function(a, b) { return a + b; } alert(s(1, 2)); //以上两种都可以 二.用函数声明定义的函数,函数可以在函

C++ DLL导出函数的两种方法(导出序号那种方法,别人看不到函数名)

第一种就直接导出函数名如下代码: #ifdef__cplusplus #define TEXPORT extern "c" _declspec(dllexport) #dlse #define TEXPORT _declspec(dllexport) TEXPORT BOOL FUN();//这就是要导出函数 这种方法查看DLL时能看到函数名. 第二种是就导出序号如下代码: bool _stdcall fun(); 在工程右键添加新项目点模块定义文件.DEF, 在在DEF文件里写 LI