恒峰网站建设问题,36kr是用wordpress吗,电子商务网站开发设计报告,做视频网站 投入好的#xff0c;我来为你总结“类和对象#xff08;中#xff09;”关于取地址运算符重载#xff0c;以及“类和对象#xff08;下#xff09;”的重点内容。我会尽量用通俗易懂的方式讲解#xff0c;帮你打好基础。
第一部分#xff1a;类和对象#xff08;中#x…好的我来为你总结“类和对象中”关于取地址运算符重载以及“类和对象下”的重点内容。我会尽量用通俗易懂的方式讲解帮你打好基础。第一部分类和对象中— 取地址运算符重载这个部分其实非常简单但在理解它之前我们需要先搞懂一个更基础的概念const成员函数。1. const成员函数让对象“只读”想象一下你有一个Date日期对象它被声明为const Date d1(2024,7,5);常量对象。这意味着你不希望d1的日期被任何函数意外修改。如何实现在成员函数的参数列表后面加上const。作用这个const实际上修饰的是隐藏的this指针。它把this指针从Date* const this一个不能改变指向的指针变成了const Date* const this一个不能改变指向并且不能通过它修改对象内容的指针。class Date { public: // 这个Print函数被const修饰意味着它不能修改调用它的对象的成员变量 void Print() const { // const修饰的是隐藏的this指针 cout _year - _month - _day endl; } // 非const函数可以修改成员变量 void SetDay(int day) { _day day; // 这是允许的 } private: int _year, _month, _day; }; int main() { const Date d1(2024, 7, 5); d1.Print(); // 正确Print是const成员函数可以被const对象调用 // d1.SetDay(10); // 错误SetDay不是const成员函数不能保证不修改d1 }简单说如果一个对象是常量const那么它只能调用那些被声明为const的成员函数因为这些函数承诺不会修改对象。2. 取地址运算符重载operator取地址运算符重载就是重载这个符号它分为两种普通取地址重载用于普通对象。const取地址重载用于const对象。class A { public: // 1. 普通对象的取地址重载 A* operator() { cout A* operator() endl; return this; // 正常情况下就是返回对象自己的地址(this) } // 2. const对象的取地址重载 const A* operator() const { cout const A* operator() const endl; return this; } };核心要点99%的情况你不需要自己写编译器会自动生成这两个函数而且生成的就完全够用了直接返回对象地址(this)。特殊用途只有在非常特殊的场景下你才需要自己实现。比如你不想让别人获取到这个对象的真实地址出于安全或设计目的你就可以胡乱返回一个地址或者返回nullptr。class Secret { public: // 重载不让别人知道我的真实地址 Secret* operator() { return nullptr; // 或者 return (Secret*)0x12345678; } };取地址重载小结它很简单了解编译器会自动生成即可。记住const成员函数的概念这个更重要。第二部分类和对象下— 核心知识点精讲这部分内容是关于类的更深层次的特性和技巧。1. 再探构造函数初始化列表之前我们初始化成员变量是在构造函数体内赋值像这样Date(int year, int month, int day) { _year year; // 这是赋值不是初始化 _month month; _day day; }更专业、更正确的方式是使用初始化列表Date(int year, int month, int day) : _year(year) // 这才是真正的初始化 , _month(month) , _day(day) {}为什么必须用初始化列表有三种特殊的成员变量必须在初始化列表中初始化引用成员变量int _ref引用必须在创建时绑定到一个实体。const成员变量const int _n常量必须在创建时赋予初始值之后不能修改。没有默认构造函数的类类型成员如果一个类成员比如Time _t它的类没有提供无参或全缺省的构造函数你就必须通过初始化列表告诉编译器如何构造它。class Time { public: Time(int hour) { ... } // 只有带参构造没有默认构造函数 }; class Date { private: int _year; const int _n; // const成员 int _ref; // 引用成员 Time _t; // 无默认构造的类成员 public: // 错误写法这些成员无法在函数体内“初始化” // Date(int year, int n, int ref) { ... } // 正确写法使用初始化列表 Date(int year, int n, int ref, int hour) : _year(year) , _n(n) // 初始化const成员 , _ref(ref) // 初始化引用成员绑定到外部变量 , _t(hour) // 调用Time的带参构造函数 {} };重要规则成员变量的初始化顺序只取决于它们在类中的声明顺序与在初始化列表中的书写顺序无关。建议保持一致以避免混淆。2. static成员属于类不属于某个对象静态成员变量用static修饰。它不属于任何一个对象而是被所有同类对象共享。它存放在静态区。必须在类外进行初始化在全局作用域语法是类型 类名::变量名 值。静态成员函数用static修饰。它没有隐藏的this指针因此不能访问普通的成员变量因为不知道访问哪个对象的只能访问静态成员变量。 调用方式可以通过对象调用(obj.func())更推荐通过类名调用(ClassName::Func())这直接表明了它是类的函数。class A { private: static int _scount; // 声明用来统计创建了多少个A对象 public: A() { _scount; } // 构造时计数1 A(const A a) { _scount; } // 拷贝构造时计数1 ~A() { --_scount; } // 析构时计数-1 // 静态成员函数没有this指针用来获取计数 static int GetACount() { return _scount; } }; // 定义并初始化静态成员变量必须在类外 int A::_scount 0; int main() { A a1, a2; A a3 a1; cout A::GetACount() endl; // 输出3 { A a4; cout A::GetACount() endl; // 输出4 } // a4析构 cout A::GetACount() endl; // 输出3 }3. 友元friend打破封装的黑客友元提供了突破private和protected访问权限的方法。友元函数一个外部的全局函数被声明为类的友元后就可以直接访问这个类的私有和保护成员。友元类类B被声明为类A的友元后类B的所有成员函数都可以直接访问类A的私有和保护成员。class A { private: int _secret 10; // 声明友元函数 friend void HackA(const A a); // 声明友元类 friend class B; }; // 友元函数的实现 void HackA(const A a) { cout I know As secret: a._secret endl; // 直接访问私有成员合法 } class B { public: void PeekA(const A a) { cout B knows As secret: a._secret endl; // 合法 } };注意友元关系是单向的A把B当朋友B不一定要把A当朋友。友元关系不能传递A是B的朋友B是C的朋友但A不是C的朋友。慎用友元它破坏了封装性增加了耦合度。但在重载输出和输入运算符时非常有用。4. 内部类类中类一个类可以定义在另一个类的内部它就是内部类。它像一个被封装在外部类里面的独立类。特性 内部类天生就是外部类的友元可以访问外部类的私有静态成员、以及通过对象访问私有成员。 内部类不占用外部类对象的大小它是独立的。 受外部类的类域和访问限定符public/private/protected限制。class Outer { private: static int _static_val; int _private_val; public: class Inner { // Inner是Outer的友元 public: void AccessOuter(const Outer o) { cout _static_val endl; // 可以直接访问外部类的静态私有成员 cout o._private_val endl; // 可以通过外部类对象访问其私有成员 } }; }; int Outer::_static_val 100;5. 匿名对象用完即焚匿名对象的生命周期只有它所在的那一行声明方式为类名(参数)。class Solution { public: int Sum_Solution(int n) { return n; } }; int main() { // 有名对象 Solution s; s.Sum_Solution(10); // 匿名对象不需要名字直接使用这一行结束就销毁 Solution().Sum_Solution(10); }用途当你只需要临时用一个对象来调用某个方法之后不再需要它时使用匿名对象非常方便。6. 编译器优化聪明的编译器现代C编译器会在不改变程序逻辑的前提下尽可能地减少对象拷贝提升效率。常见优化场景连续构造拷贝构造- 优化为直接构造。传值返回时局部对象拷贝到临时对象再拷贝到接收对象- 优化为直接构造接收对象。A GetA() { return A(10); // 理论上构造A(10) - 拷贝给临时对象 - 拷贝给main中的aa } // 实际上优化后直接在GetA函数里为main中的aa分配空间并构造 int main() { A aa GetA(); // 优化后可能只有一次构造操作 }注意优化因编译器而异但理解这些优化能帮助你写出更高效的代码。总结与联系特性核心思想为什么重要取地址重载/const成员函数控制对象地址的获取和对象的“只读”性。完善对对象行为的控制是理解C封装和常量正确性的基础。初始化列表真正初始化成员的地方尤其是特殊成员。正确的初始化是避免未定义行为的关键是编写稳健类的基石。static成员属于类本身的变量和函数被所有对象共享。实现对象间通信、管理类级别资源如计数器的必备工具。友元授予特定函数或类访问私有成员的“特权”。在需要突破封装时如输入输出流重载提供灵活性。内部类将紧密关联的类封装在一起增强代码内聚性。用于设计更清晰、更模块化的代码结构。匿名对象临时使用的对象生命周期极短。简化代码避免创建不必要的命名对象。编译器优化编译器自动减少不必要的对象拷贝。理解编译器行为有助于写出性能更高的C代码。内部类| 将紧密关联的类封装在一起增强代码内聚性。 | 用于设计更清晰、更模块化的代码结构。 ||匿名对象| 临时使用的对象生命周期极短。 | 简化代码避免创建不必要的命名对象。 ||编译器优化| 编译器自动减少不必要的对象拷贝。 | 理解编译器行为有助于写出性能更高的C代码。 |希望这份总结能帮助你清晰地理解这些概念这些知识是学习后面更复杂的C特性如模板、智能指针等的重要基础。如果还有不清楚的地方可以随时再问。