const 成员函数
先声明一个 Demo 类:
#ifndef CONST_OBJECT_H_
#define CONST_OBJECT_H_
#include <string>
class Demo {
private:
int value;
std::string id;
public:
Demo();
Demo(int, std::string);
~Demo();
void show();
};
Demo::Demo() {
value = 0;
id = "no id";
}
Demo::Demo(int v, std::string s) {
value = v;
id = s;
}
Demo::~Demo() {
std::cout << "Class Demo's Destructor." << std::endl;
}
void Demo::show() {
cout << "Value is " << value << ". ID is " << id << std::endl;
}
#endif
接下来看一段代码:
#include "const_object.h"
#include <iostream>
int main(int argc, char** args) {
const Demo d1 = Demo(3, "Demo1");
d1.show();
return 0;
}
错误信息如下:
错误原因:show() 的代码无法确保调用对象不被修改,即 show 函数不保证 const 对象 d1 不会被修改。
我们以前通过将函数参数声明为 const 引用或指向 const 的指针来解决这种问题。但是这里存在语法问题 —— show() 方法没有任何参数。相反,它使用的对象是由方法调用隐式提供的。所以需要一种新的语法 —— 确保成员函数不会修改调用对象。 C++ 的解决方案是将 const 关键字放在函数的括号后面。也就是说,show() 声明和定义应该如下所示:
class Demo {
...
void show() const;
...
};
void Demo::show() const {
...
}
this 指针
到目前为止,我们的成员函数都只涉及到它调用的对象,但有时候成员函数会可能会涉及到多个对象,这种情况下就会用到 C++ 的 this 指针。
定义一个成员函数,比较两个 Demo 对象的 value 值,并返回值较大的那个对象。
const Demo& Demo::max(const Demo & d) const {
if (d.value > value)
return d;
return ???;
}
该函数隐式地访问一个对象(调用对象),显式地访问另一个对象(参数),并返回其中一个对象的引用。括号中的 const 表示该函数不会修改参数;括号后的 const 表明该函数不会修改调用对象;由于该函数返回两个 const 引用中的一个,因此返回类型也应该是 const 引用。 其中,d.value 是参数的 value,value 是调用 max() 的对象的 value。如果参数的 value 比调用对象的 value 大,那么就返回引用参数,否则返回调用该方法的对象。但问题在于如何表示调用对象?如果调用 d1.max(d2),则 d 是 d2 的引用,但 d1 没有别名。 C++ 解决这个问题的方法是 —— 使用被称为 this 的特殊指针。this 指针指向用来调用成员函数的对象(this 被作为隐藏参数传递给函数)。这样,函数调用 d1.max(d2) 将 this 设置为对象 d1 的地址。一般来说,所有类的成员函数都将 this 指针设置为调用它们的对象的地址。max() 中的 value 其实就是 this->value 的简写。
下图是《C++ Primer Plus》中关于 this 的图解:
const Demo& Demo::max(const Demo & d) const {
if (d.value > value)
return d;
return *this;
}
顺便说一下,了解 this 指针就可以更深入的了解 C++ 的工作方式。C++ 在处理方法的定义时,会进行一些转换。例如,将 max() 方法转换为下面的形式:
const Demo& max(const Demo* this, const Demo& d){};
即将 Demo:: 限定符转换成函数参数(指向 Demo 的 this 指针),然后用这个指针来访问类成员。 同样的,在调用方法的时候,也会进行一些转换:
d1.max(d2);
max(&d1, d2);
这样就将调用对象的地址赋值给 this 指针。
|