Last Updated: 2023-12-24 06:14:59 Sunday
-- TOC --
由于C++兼容历久弥新的C,C语言中的const申明所支持的,C++显然都要支持。而C++引入了很多新的语法规则,对const申明也进行了扩展。
被const修饰的成员函数,被称为const method
,或者read-only method
,即他们只能读取对象的成员变量,不能修改。
struct ClockOfTheLongNow {
--snip--
int get_year() const {
return year;
}
private:
int year;
};
有两个术语,accessor
和mutator
,accessor就是有const修改的class method。
const接口是function signature的一部分!
引用,reference,是C++引入的一个新特性,它没有指针灵活,但比指针安全。常见一些成员函数接口参数,就是对象的引用。
bool is_leap_year(const ClockOfTheLongNow& clock) {
if (clock.get_year() % 4 > 0) return false;
if (clock.get_year() % 100 > 0) return true;
if (clock.get_year() % 400 > 0) return false;
return true;
}
在is_leap_year函数范围内,不允许出现没有const修饰的clock的成员函数接口。
由于get_year已经被申明为const,因此上面的测试代码,可以顺利编译通过。在is_leap_year的执行范围内,clock这个引用对象的状态(成员变量),不允许被修改,不管它们是否有自己的const申明。
在C++中,字符串常量的申明,必须使用const,否则会有warning:
struct Avout {
const char* name = "Erasmas";
const int a = 1;
};
如上定义的name变量,必须使用const,否则g++编译器会给出一个warnning。而gcc不会。这是体现出C++语法要求更严格!
如果希望const变量能够在对象初始化的时候,其值由传入的参数指定,这时,你需要使用C++的初始化列表。const变量除了在定义的地方赋值,不能有其它显式地的赋值,如果是对象成员,还能通过初始化列表,仅此。
有个比较tricky的细节,对象初始化列表会覆盖已经赋值的const变量:
#include <iostream>
#include <string>
using namespace std;
struct xyz{
const int a {1};
xyz(int x): a{x} {}
};
int main(void) {
xyz z{2};
cout << z.a << endl;
return 0;
}
输出2,原来定义的1被初始化列表覆盖了。我们可以这样来理解这个feature:const只是readonly,值可以是runtime确定的,确定后readonly,而runtime确定const值,就是在对象初始化的时候。
如果static成员变量没有const申明,那么这个static成员变量的初始化,只能在global scope下进行,具体请参考:C++ class中的static理解
但是有一个例外,就是static const,这类成员变量,就直接在申明的地方初始化。
class Apple
{
public:
// 被const修饰的static变量在c++11中可以在类内被直接初始化。
const static int i {10};
};
我是这样理解的:被const修饰的变量,可以在编译期有可用的值,而被constexpr修饰的变量,必须在编译器有可用的值。也就是说,const包含了constexpr的意思。也因此,需要在编译期使用的变量,建议都是用constexpr。而const,基本都用于修饰函数接口的入参,以及作为function signature的一部分。
本文链接:https://cs.pynote.net/sf/c/cpp/202208101/
-- EOF --
-- MORE --