面试题答案
一键面试1. const成员函数和const对象之间的联系和限制
- 联系:const对象只能调用const成员函数。这是因为非const成员函数可能会修改对象的状态,而const对象的状态是不允许被修改的,所以编译器只允许const对象调用不会修改对象状态的const成员函数。
- 限制:
- 非const对象既可以调用const成员函数,也可以调用非const成员函数。
- const成员函数不能修改对象的非mutable数据成员(除非这些数据成员被声明为mutable),因为其设计初衷就是保证在调用函数时对象状态不被改变。
2. 为什么有些成员函数需要声明为const
- 表明函数不会修改对象状态:这样可以让代码的意图更清晰,调用者可以明确知道调用该函数不会改变对象的内部数据。例如,访问器(getter)函数通常会声明为const,因为它们只是返回对象的某些属性值,而不应该修改对象。
- 提高函数的可复用性:一个声明为const的成员函数既可以被const对象调用,也可以被非const对象调用。如果没有声明为const,就只能被非const对象调用,限制了函数的使用场景。
3. mutable成员变量在const成员函数中的修改合法性
在C++中,mutable关键字修饰的成员变量可以在const成员函数中被修改。这是因为mutable变量的设计目的就是为了允许在const成员函数中改变其值,用于一些与对象逻辑状态无关的变量,比如用于记录函数调用次数等辅助信息。
代码示例
#include <iostream>
class MyClass {
private:
int data;
mutable int callCount;
public:
MyClass(int value) : data(value), callCount(0) {}
// const成员函数,不能修改非mutable成员变量
int getData() const {
callCount++;
return data;
}
// 非const成员函数,可以修改成员变量
void setData(int value) {
data = value;
callCount++;
}
};
int main() {
MyClass obj(10);
const MyClass constObj(20);
std::cout << "Non - const object getData: " << obj.getData() << std::endl;
std::cout << "Non - const object callCount: " << obj.callCount << std::endl;
std::cout << "Const object getData: " << constObj.getData() << std::endl;
std::cout << "Const object callCount: " << constObj.callCount << std::endl;
// 下面这行代码会报错,因为constObj是const对象,不能调用非const成员函数
// constObj.setData(30);
obj.setData(30);
std::cout << "After setData, Non - const object getData: " << obj.getData() << std::endl;
std::cout << "After setData, Non - const object callCount: " << obj.callCount << std::endl;
return 0;
}
在上述代码中,MyClass
类有一个data
成员变量和一个mutable
修饰的callCount
成员变量。getData
函数是一个const成员函数,它可以读取data
,同时也能修改callCount
。setData
是非const成员函数,可以修改data
和callCount
。通过constObj
和obj
的调用示例,展示了const对象对函数调用的限制以及mutable变量在const成员函数中的使用。