共计 1751 个字符,预计需要花费 5 分钟才能阅读完成。
1. this 指针与成员函数调用约定
在 C ++ 中,每个非静态成员函数都隐式包含一个名为 this 的指针参数。编译器会自动将其转换为类似 ClassName::func(ClassName* this) 的形式。这种调用约定被称为__thiscall(在 MSVC 中),其特点:

this指针通常通过 ECX 寄存器传递(x86 架构)- 成员函数调用会被编译器进行 name mangling 处理
- 访问控制(public/private)在编译期检查,运行时无额外开销
class Example {
public:
void show() {// 实际被编译为:void show(Example* this)
std::cout << this->value;
}
private:
int value;
};
2. 成员访问的陷阱与解决方案
陷阱 1:悬空指针访问
class Resource {
public:
void use() { /* 使用资源 */}
};
Resource* createBadResource() {
Resource local;
return &local; // 返回局部对象地址!}
// 错误用法:Resource* res = createBadResource();
res->use(); // 未定义行为!
陷阱 2:const 成员函数修改成员
class Counter {
public:
void increment() const {count++; // 编译错误:不能在 const 成员函数中修改成员}
private:
mutable int count; // 解决方案:声明为 mutable
};
3. 典型场景代码示例
场景 1:基本成员函数调用
class Rectangle {
public:
// 正确:通过 this 隐式访问
double area() const {return width * height;}
void scale(double factor) {
// 显式使用 this 增强可读性
this->width *= factor;
this->height *= factor;
}
private:
double width = 1.0;
double height = 1.0;
};
场景 2:静态函数访问非静态成员
class Logger {
public:
static void log(const std::string& msg) {
// 错误:不能直接访问非静态成员
// std::cout << prefix << msg;
// 正确方案:通过实例访问
Logger instance;
std::cout << instance.prefix << msg;
}
private:
std::string prefix = "[LOG]";
};
场景 3:通过指针 / 引用调用
class Sensor {
public:
float read() {return calibrate(rawValue());
}
virtual float rawValue() = 0; // 多态调用
private:
float calibrate(float v) {return v * 1.02f;}
};
// 使用示例:Sensor* sensor = new Thermometer();
float val = sensor->read(); // 通过指针虚调用
Sensor& ref = *sensor;
val = ref.read(); // 通过引用调用
4. 性能优化建议
-
对简单成员函数使用
inline(现代编译器会自动优化)class Point { public: inline int x() const { return m_x;} // 适合 inline }; -
避免不必要的成员拷贝:
class BigData { public: // 不好:返回大型对象副本 std::vector<double> getData() { return data;} // 更好:返回 const 引用 const std::vector<double>& getData() const { return data;} };
5. 生产环境最佳实践
- 对不修改成员的函数始终声明为
const - 多态基类的析构函数必须为
virtual - 优先使用
->操作符而非(*ptr).语法 - 在头文件中实现模板成员函数
- 使用
mutable要谨慎,仅用于真正的逻辑 const 场景
思考题
- 当通过基类指针调用虚函数时,编译器如何确定调用哪个实现?
- 为什么静态成员函数不能声明为
const?
正文完
