【C++】const对象和const成员

简介: 【C++】const对象和const成员

如果我们在定义一个对象之后,不希望在后面对这个对象进行修改,那么我们可以把这个对象声明为const对象。

声明为const对象之后,这个对象的所有数据成员后面都不能被修改!


const对象


定义类对象时可以将其指定为const对象。定义后const对象不能再被修改。

const对象不能调用非const类型的成员函数。

有两种方法来定义一个const对象:

const 类名 对象名

类名 const 对象名

这两种方法是等价的。


如果一个对象被定义成const对象,那么它就不能调用这个类中的非const成员函数。

const对象调用的成员函数一定都得是const!


//const
const CTime time4(10);
CTime const time5;


如果你用const对象引用了这个类中的非const成员函数,就会报错:


错误  1   error C2662: “int CTime::getHour(void)”: 不能将“this”指针从“const CTime”转换为“CTime &”
e:\chenhaoxiang\20170603\test2\test2\mian.cpp   34  1   test2


其实就是告诉我们const对象不能引用非const成员函数

为什么要有这个规则:

因为在非const成员函数内部可能对对象进行修改,比如set函数

这个规则也就是强制用户不要对const成员进行错误的修改


const成员


1.const数据成员


也就是变量,比如实例中的m_hour,m_minute是普通数据成员


在类内部使用const关键字来声明const数据成员。const数据成员的值不能被修改。

初始化时比较特殊,只能通过初始化列表初始化。不能在构造函数里赋值。


2.初始化列表


初始化列表:

除了在构造函数中对数据成员进行初始化,C++还提供另外一种方法来对数据成员进行初始化

初始化列表并不是在构造函数内进行初始化

构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。


const int num;


必须初始化,而且不能在构造函数中初始化!


CTime::CTime() : num(10){
    m_hour = 0;
    m_minute = 0;
    m_second = 0;
    m_nNum++;
    cout << m_nNum << endl;
}
CTime::CTime(int hour) : num(10){
    this->m_hour = hour;
    //(*this).m_hour = hour; //效果一样的
}
//复制构造函数
CTime::CTime(CTime& time) : num(10){
    m_hour = time.m_hour;
    m_minute = time.m_minute;
    m_second = time.m_second;
    //cout << "进入复制构造函数" << endl;
}



每一个构造函数都需要初始化这个const成员,而且复制构造函数也需要初始化num,因为复制构造函数也是一种构造函数!


3.const成员函数


const成员函数只能被const对象引用。const成员函数内可以引用const数据成员,也可以引用非const数据成员,但不能修改非const数据成员的值。但不能调用非const成员函数。


int getNum() const;


对于const函数的外部定义,也需要写const限定符


int CTime::getNum() const {
    return num;
}


const成员函数存在的意义在于它能被const常对象调用


CTime const time5;
    cout << time5.getNum() <<endl;


如果在const成员函数的定义中出现了任何修改对象成员数据的现象,都会在编译时被检查出来


如果我们是真的想在const成员函数中修改值呢,比如我需要m_age++;

比如下面定义了一个m_age 类成员:


int m_age;


int CTime::getNum() const {
    if (m_age == 0){
        m_age++;
    }
    else{
        m_age = 0;
    }
    return num;
}


假如我们不做其他事情,这样的写法,在编译时是无法通过的。


有些时候,我们想要让const函数具有修改某个成员数据值的能力。

比如一些内部的状态量,对外部用户无所谓,但是对整个对象的运行却大有用处,如支持缓存的技术。

遇到这种问题,我们可以把一个成员数据定义为mutable(多变的),它表示这个成员变量可以被const成员函数修改却不违法。

比如下面定义了这样一个m_age 类成员:


mutable int m_age;


int CTime::getNum() const {
    if (m_age == 0){
        m_age++;
    }
    else{
        m_age = 0;
    }
    return num;
}


这样,即使像getNum()这样的const成员函数修改它也是合法的。

但需要注意的时,不要滥用mutabe描述符,如果在某个类中只有少数一部分是被允许const常量函数修改的,使用mutable是再合适不过的。如果大部分数据都定义为mutable,那么最好将这些需要修改的数据放入另一个独立的对象里,并间接地访问它。


源代码下载地址:

GITHUB源码下载地址: 点我进行下载


目录
相关文章
|
6天前
|
Java C++ Python
【C++从练气到飞升】06---重识类和对象(二)
【C++从练气到飞升】06---重识类和对象(二)
|
6天前
|
编译器 C++
【C++从练气到飞升】06---重识类和对象(一)
【C++从练气到飞升】06---重识类和对象(一)
|
6天前
|
存储 编译器 C语言
【C++从练气到飞升】02---初识类与对象
【C++从练气到飞升】02---初识类与对象
|
8天前
|
C++
【C++】类与对象(日期计算器)
【C++】类与对象(日期计算器)
17 0
|
8天前
|
编译器 C++
【C++】类与对象(static、explicit、友元、隐式类型转换、内部类、匿名对象)
【C++】类与对象(static、explicit、友元、隐式类型转换、内部类、匿名对象)
8 2
|
8天前
|
编译器 C++
【C++】类与对象(运算符重载、const成员、取地址重载)
【C++】类与对象(运算符重载、const成员、取地址重载)
13 2
|
8天前
|
存储 编译器 对象存储
【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)
【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)
7 0
|
8天前
|
存储 编译器 C语言
【C++】类与对象【定义、访问限定符、this指针】
【C++】类与对象【定义、访问限定符、this指针】
6 1
|
编译器 C++
[C++基础]-类和对象(下)
[C++基础]-类和对象(下)
|
7天前
|
设计模式 安全 算法
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
16 0