既然成员函数在内存中只有一份那调用不同对象的成员函数时函数内部是如何区分要操作哪个对象呢。当调用一个非静态成员函数时编译器会隐式地把调用该函数的对象的地址指针作为第一个参数传递进去这就是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。如果成员函数没有涉及到成员变量可以正常执行。涉及成员变量时会因为this-mA nullptr-mA而导致程序崩溃。类中存在虚函数当一个类有虚函数时编译器会为这个类创建一个隐藏的表叫做虚函数表vptr。这个表存放了所有虚函数的地址。对于对象opjobj-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关键字是C11引入的推荐使用让意图更清晰)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 运算符重载的语法成员函数的形式// 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;}非成员函数的形式通常使用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::coutstd::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 iostreamstruct 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.0std::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;}