当前位置: 首页 > news >正文

2.1.8 this指针

既然成员函数在内存中只有一份,那调用不同对象的成员函数时,函数内部是如何区分要操作哪个对象呢。

当调用一个非静态成员函数时,编译器会隐式地把调用该函数的对象的地址指针作为第一个参数传递进去,这就是this指针,类型是className* const。obj1.show()在编译器看来更像是show(&obj1)。

// 对于 obj1.show(),this 指向 obj1,所以 this->mA 就是 obj1.mA(值为10)。
// 对于 obj2.show(),this 指向 obj2,所以 this->mA 就是 obj2.mA(值为30)。

2.1.9 静态成员函数

在 C++ 中,静态成员函数(Static Member Function)是类的成员函数,但它不属于类的某个具体对象,而是属于类本身。静态成员函数可以直接通过类名调用,无需创建类的实例(对象),并且它只能访问类的静态成员(静态变量或其他静态函数),不能直接访问非静态成员(普通变量或普通函数)。

静态成员函数没有this指针,因此无法访问类的非静态成员(变量或函数),因为非静态成员属于对象实例。

声明周期与类相同,静态成员函数在程序加载时就被初始化,直到程序结束才销毁。

调用:

class MyClass {
public:
static void StaticFunction(); // 静态成员函数声明
};
MyClass::StaticFunction(); // 直接通过类名调用
空指针访问成员函数

核心思想是函数调用并不依赖与对象地址。成员函数是存放在代码区的,使用nullptr调用成员函数是可以调用的,只是传入的this指针是nullptr。

  1. 如果成员函数没有涉及到成员变量,可以正常执行。

  2. 涉及成员变量时会因为this->mA => nullptr->mA而导致程序崩溃。

  3. 类中存在虚函数

    1. 当一个类有虚函数时,编译器会为这个类创建一个隐藏的表,叫做虚函数表vptr。这个表存放了所有虚函数的地址。
    2. 对于对象opj,obj->vptr->doSomething()
    a. 通过对象指针 `p` 找到对象本身。
    b. 从对象的内存中读取 `vptr`(虚函数表指针)。
    c. 通过 `vptr` 找到虚函数表。
    d. 在虚函数表中查找 `doSomething` 的地址。
    e. 跳转到该地址执行函数。

2.1.10 虚函数

虚函数是在基类中使用virtual关键字声明的成员函数。它允许你在派生类中对该函数进行重写(Override),并且当你通过基类的指针或引用来调用该函数时,程序会动态地根据指针或引用实际所指向的对象类型,来调用相应派生类中的版本,而不是基类的版本。

核心目的是实现运行时多态,也成为动态绑定,就是用一个统一的接口,去处理多种不同类型的对象。

#include <iostream>
// 基类:动物
class Animal {
public:
// 使用 virtual 关键字声明为虚函数
virtual void speak() {
std::cout << "Some generic animal sound!" << std::endl;
}
};
// 派生类:狗
class Dog : public Animal {
public:
// 重写 speak 函数 (override关键字是C++11引入的,推荐使用,让意图更清晰)
void speak() override {
std::cout << "Woof! Woof!" << std::endl;
}
};
// 派生类:猫
class Cat : public Animal {
public:
void speak() override {
std::cout << "Meow!" << std::endl;
}
};
int main() {
Dog myDog;
Cat myCat;
Animal* animalPtr1 = &myDog;
Animal* animalPtr2 = &myCat;
std::cout << "Calling speak() via pointers (with virtual):" << std::endl;
animalPtr1->speak(); // 现在它会正确地叫 "Woof! Woof!"
animalPtr2->speak(); // 现在它会正确地叫 "Meow!"
return 0;
}

2.2 C++运算符重载

什么是运算符重载:相对于某个class来说,重新定义已有的运算符,使得其工作在我们期待的情况下。例如

Vector v1(1, 2), v2(3, 4);
Vector v3 = v1 + v2; // 希望实现向量相加
2.2.1 运算符重载的语法
  1. 成员函数的形式
// Vector: 返回值
// Vector:: : 表示这是一个成员函数,属于Vector类。
// const Vector& other: 表示一个常量引用,避免拷贝开销,保证只读
Vector Vector::operator+(const Vector& other) const;
class Vector {
public:
double x, y;
// 构造函数
Vector(double x = 0, double y = 0) : x(x), y(y) {}
// 重载 + 运算符
Vector operator+(const Vector& other) const {
return Vector(x + other.x, y + other.y); // 返回新对象
}
};
int main() {
Vector v1(1.0, 2.0);
Vector v2(3.0, 4.0);
Vector v3 = v1 + v2; // 调用 operator+,结果为 (4.0, 6.0)
std::cout << "v3: (" << v3.x << ", " << v3.y << ")" << std::endl;
return 0;
}
  1. 非成员函数的形式
    通常使用friend关键字,友元函数。
class Vector {
// ... 其他成员 ...
friend Vector operator+(const Vector& a, const Vector& b);
};
Vector operator+(const Vector& a, const Vector& b) {
return Vector(a.x + b.x, a.y + b.y);
}
2.2.2 常见运算符重载

只要某个表达式里出现了你自定义的类型,并且用到了某个运算符,而这个运算符对该类型没有现成的、可用的实现,编译器就会去查找是否存在针对该类型、该运算符的重载函数。找到了就用,找不到就报错。

Vector& Vector::operator=(const Vector& other) {
if (this != &other) { // 防止自赋值
x = other.x;
y = other.y;
}
return *this;
}
int& Vector::operator[](int index) {
if (index == 0) return x;
else if (index == 1) return y;
else throw std::out_of_range("Index out of range");
}
// std::ostream& os是输出流对象,如std::cout
std::ostream& operator<<(std::ostream& os, const Vector& v) {
os << "(" << v.x << ", " << v.y << ")";
return os;
}
std::istream& operator>>(std::istream& is, Vector& v) {
is >> v.x >> v.y;
return is;
}
// 前置 ++
Vector& Vector::operator++() {
++x;
++y;
return *this;
}
// 后置 ++(用 int 参数区分,没有逻辑原因,就是一个占位参数,用于区分)
Vector Vector::operator++(int) {
Vector temp = *this;
++(*this);
return temp;
}
// 关系运算符重载
bool operator<(const Person& other) const {
return age < other.age;
}
bool operator>(const Person& other) const {
return age > other.age;
}
bool operator<=(const Person& other) const {
return age <= other.age;
}
bool operator>=(const Person& other) const {
return age >= other.age;
}

输入输出流重载说明:std::ostream& operator<<(std::ostream& os, const Vector& v)
首先这是一个函数,函数名字是operator<<,函数的输出类型是std::ostream&,输入类型是std::ostream& const Vector& v相当于(std::cout << v)的重载后的输出可以是std::cout以便格式化输出Vector类型之后还能够继续链式输出其他内容。

// 输入输出流重载
#include <iostream>
struct Vector {
double x, y;
};
// 输出流重载
std::ostream& operator<<(std::ostream& os, const Vector& v) {
os << "(" << v.x << ", " << v.y << ")";
return os;
}
// 输入流重载
std::istream& operator>>(std::istream& is, Vector& v) {
is >> v.x >> v.y;
return is;
}
int main() {
Vector v1, v2;
// 输入
std::cout << "Enter Vector 1 (x y): ";
std::cin >> v1; // 例如输入: 1.0 2.0
std::cout << "Enter Vector 2 (x y): ";
std::cin >> v2; // 例如输入: 3.0 4.0
// 输出
std::cout << "Vector 1: " << v1 << std::endl; // 输出: Vector 1: (1.0, 2.0)
std::cout << "Vector 2: " << v2 << std::endl; // 输出: Vector 2: (3.0, 4.0)
return 0;
}
http://www.jsqmd.com/news/1099715/

相关文章:

  • 免费开源NoFences桌面分区管理工具:3步打造高效整洁Windows桌面
  • Day10 | SFT 训练实操——用 QLoRA 微调 Qwen3-8B
  • BetterJoy完整指南:让Switch手柄在PC游戏上完美运行
  • 智谱大模型LLM一面,人麻了!!!
  • 【JAVA毕设源码分享】基于springboot的小区公共收益管理系统 的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 光电经纬仪测量中的坐标系体系及其应用
  • CPT Markets:把外汇用户支持体系做到位——维度复盘与提示整理
  • 抖音内容批量采集与智能管理工具:从零到精通的完整指南
  • OpenAI / Claude API 报错 401、403、429 怎么解决?一文讲清 API Key 失效排查思路
  • 量子虚时演化算法原理与sine-Gordon模型模拟实践
  • FreeCAD源码分析: Property View
  • 我一个人 11 天交付了两个模块——不是会分身,是让两个 AI 打了配合
  • 1115.交替打印FooBar
  • 【课程设计/毕业设计】基于 SpringBoot 的农业设备销售订单管理系统的设计与实现 基于 SpringBoot 的智慧农机综合服务管理系统【附源码、数据库、万字文档】
  • 修改很简单,但网上讲这点的文档不多,因此多记一笔。另外基于out_ptr会临时转移所有权这点来看,共享所有权模型的std::shared_ptr其实并不适合使用out_ptr,虽然标准没有禁止甚至还要
  • playwright-拖拽验证码
  • LeWorldModel:基于JEPA的轻量化世界模型实践指南
  • 为什么要将 RTF 转换为 PDF?
  • 告别泰拉瑞亚原版限制:tModLoader模组开发实战手册
  • Opencv延迟优化
  • 项目包含项目源码、项目文档、数据库脚本、软件工具等资料;
  • 欧姆龙NJ系列EtherCAT总线通信常用系统状态字
  • Agibot第15000台人形机器人下线,具身AI量产加速
  • 【课程设计/毕业设计】基于 SpringBoot 的电子化招投标数据统计分析系统的设计与实现 基于 SpringBoot 的中小型企业线上招标管理平台【附源码、数据库、万字文档】
  • 【GitHub】 fastText:当“快“成为核心竞争力——从源码拆解 Facebook 的 10 亿词级 NLP 利器
  • 新版通达信多空主力拉升1主图2副1选股指标套装工具
  • 破局生物医药研发:实验数据标准化管理平台如何重塑科研新范式
  • web9使用RESTful完整项目的用户增删改查的项目代码
  • 从厨房秤到智能称重:用STM32F103和HX711打造你的第一个物联网传感器节点
  • Jmeter性能测试与SQL优化——电影收藏清单小程序获取收藏列表