设为首页 加入收藏

TOP

68.C++中的const(四)
2023-07-23 13:35:42 】 浏览:113
Tags:68.C const
与不修改类对象的函数。例如:

const Screen blankScreen;
blankScreen.display();   // 对象的读操作
blankScreen.set(‘*’);    // 错误:const类对象不允许修改

??C++中的常量对象,以及常量对象的指针或引用都只能调用常量成员函数。

??要声明一个const类型的类成员函数,只需要在成员函数参数列表后加上关键字const,例如:

class Screen 
{
public:
   char get() const;
};

在类外定义const成员函数时,还必须加上const关键字:

char Screen::get() const 
{
   return screen[cursor];
}

若将成员成员函数声明为const,则该函数不允许修改类的数据成员。例如:

class Screen 
{
public:
    int get_cursor() const {return cursor; }
    int set_cursor(int intival) const { cursor = intival; }
};

在上面成员函数的定义中,get_cursor()的定义是合法的,set_cursor()的定义则非法。

值得注意的是,把一个成员函数声明为const可以保证这个成员函数不修改数据成员,但是,如果据成员是指针,则const成员函数并不能保证不修改指针指向的对象,编译器不会把这种修改检测为错误。例如:

class Name
{
public:
    void setName(const string &s) const;
    char *getName() const;
private:
    char *m_sName;
};
 
void setName(const string &s) const 
{
    m_sName = s.c_str();      // 错误!不能修改m_sName;
 
    for (int i = 0; i < s.size(); ++i) 
        m_sName[i] = s[i];    // 不是错误的
}

const成员函数可以被具有相同参数列表的非const成员函数重载,例如:

class Screen 
{
public:
    char get(int x,int y);
    char get(int x,int y) const;
};

在这种情况下,类对象的常量性决定调用哪个函数。

const Screen cs;
Screen cc2;
char ch = cs.get(0, 0);  // 调用const成员函数
ch = cs2.get(0, 0);     // 调用非const成员函数

const成员函数不能修改类对象数据成员的深层解析:

调用成员函数时,通过一个名为this的隐式参数来访问调用该函数的对象成员。例如:

Name bozai;
bozai.setName("bozai");
bozai.getName("BOZAI");

调用setName时隐式传入 this 形参,通过改变 this->m_sName 的值来改变bozai对象的m_sName。

当调用getName时,同样是隐式传入 this 形参,不过此时的 this 被 const 修饰了,所以不能通过 this 修改对象的成员了。

原文链接:https://blog.csdn.net/weixin_45773137/article/details/126297568

4.constexpr 限定符

4.1常量表达式

常量表达式:指值不会改变并且在编译过程就能得到结果的表达式;字面值、用常量表达式初始化的const对象也是常量表达式。
字面值类型:算术类型、引用和指针都属于字面值类型,自定义类、IO库,string类型则不属于字面值类型,不能被定义成constexpr;

一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定, 例如:

const int max_files = 20;//max_files是常量表达式
const int limit = max_files + 1; //limit是常量表达式
int staff_size = 27;//staff_size不是常量表达式 
const int sz = get_size();//sz不是常责表达式

??尽管sz本身是一个常量,但它的具体值直到运行时才能获取到,所以也不是常量表达式。

4.2constexpr变量

??在一个复杂系统中,很难(几乎肯定不能)分辨一个初始值到底是不是常量表达式。当然可以定义一个const变量并把它的初始值设为我们认为的某个常量表达式,但在实际使用时,尽管要求如此却常常发现初始值并非常量表达式的情况。可以这么说,在此种情况下,对象的定义和使用根本就是两回事儿。

??C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化:

constexpr int mf = 20;//20是常量表达式
constexpr int limit= mf + l;//mf + 1是常量表达式
constexpr int sz = size();//只有当size是一个constexpr函数时才是一条正确的声明语句

4.3constexpr函数

??尽管不能使用普通函数作为constexpr变量的初始值,但是正如C++ Primer6.5.2节(第214页) 将要介绍的,新标准允许定义一种特殊的constexpr函数。这种函数应该足够简单以使得编译时就可以计算其结果,这样就能用constexpr函数去初始化constexpr变量了。

constexpr函数:指能用于常量表达式的函数,其定义方式和普通函数类型;
定义规则

  • 函数的返回类型及所有形参类型都是字面值类型
  • 函数体中只有一条return 语句
constexpr int func(int n)
{
	return n;
}
int main()
{
	int n=10;
	const int m=10;
	constexpr int i = func(10);//正确,i是一个常量表达式
	constexpr int j = func(n);//错误,n不是字面值
	constexpr int k = func(m+1);//正确,k是一个常量表达式
	return 0;
}
由于func是constexpr函数,编译器能在程序编译时验证func函数返回的是常量表达式,如上面的j,因为n不是常量,所以会在编译期间报错,方便修正
不仅如此,对于constexpr函数,编译器会把constexpr函数的调用替换成其结果值,为了能在编译过程中随时展开,constexpr函数被隐式地指定为内联函数,关于内联函数在这篇C++内联函数博客中有详细介绍
简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值,如果传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了

————————————————
版权声明:本文为CSDN博主「倒地不起的土豆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.cs

首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Leetcode Practice -- 数组 下一篇C++/Qt网络通讯模块设计与实现(三)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目