新乡移动网站建设自动建站源码

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

新乡移动网站建设,自动建站源码,网站运营需要 做哪些工作内容,模板建站难度大面向对象三大特性#xff1a;封装、继承、多态 RE: 封装 C把数据和方法封装在类里面迭代器和适配器 继承 1 基类 派生类 一个类可以派生自多个类#xff0c;这意味着#xff0c;它可以从多个基类继承数据和函数。定义一个派生类#xff0c;我们使用一个类派生列表…面向对象三大特性封装、继承、多态 RE: 封装 C把数据和方法封装在类里面迭代器和适配器 继承 1 基类 派生类 一个类可以派生自多个类这意味着它可以从多个基类继承数据和函数。定义一个派生类我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名形式如下 class 派生类子类: 访问修饰符 基类父类注访问修饰符是 public、protected 或 private 其中的一个未使用它则默认是 private假设有一个基类 ShapeRectangle 是它的派生类如下所示 #include iostream using namespace std;// 基类 class Shape {public:void setWidth(int w){width w;}void setHeight(int h){height h;}protected:int width;int height; };// 派生类 class Rectangle: public Shape {public:int getArea(){ return (width * height); } };int main(void) {Rectangle Rect;Rect.setWidth(5);Rect.setHeight(7);// 输出对象的面积cout Total area: Rect.getArea() endl;return 0; }2 访问控制和继承 访问 public protected private 同一个类 yes yes yes 派生类 yes yes no 外部的类 yes no no3 赋值兼容转换切片 派生类对象 可以赋值给 基类的对象/基类的指针/基类的引用 。 切片把派生类中基类那部分切来赋值过去 赋值语句父类对象 子类对象 而 基类对象不能赋值给派生类对象 。 注单独的语法规则不是类型转换没有产生临时变量与下述引例机制不同 引例截断和提升 // 类型转换会产生临时变量 int i 1234; printf(%x\n, i);// 4d2 // 截断 char ch i; printf(%x\n, ch);// ffffffd2 // 提升 i ch; printf(%x\n, i);// ffffffd2const int ref_i i;// 临时变量具有常性 printf(%d\n, ref_i);// -46const char ref_ch ch;// 临时变量具有常性 printf(%d\n, ref_ch);// -461234 的二进制表示为10011010010除 2 取余法 补全至16位0000 0100 1101 0010 然后将每一组二进制转换为十六进制 0000 0 0100 4 1101 D大小写皆可 0010 2 最终组合成十六进制4d2 第一个输出结果4d2 截断 因为 char 类型只占用 1 个字节8 位而 i 是一个 32 位的整数在赋值给 char 时只保留了最低 8 位的内容1101 0010即 0xd2其余高位被截断。 留下的内容最高位是 1表明这是一个负数当 char 被提升为 int 以打印时会进行符号扩展高位会被填充为 1使得 ch 变成 0xFFFFFFD2在 32 位系统上。 第二个输出结果ffffffd2 提升: ch 是有符号类型且其值为 1101 0010 找到补码当前的二进制数 11010010 就是补码。 求反码将所有位取反11010010 取反后得到00101101 加 100101101 1 00101110 这个结果是 00101110对应的十进制值是 46。 因为符号位是 1表示这是一个负数所以最终值为-46。 ch 是有符号类型且其值为 0xD2-46 in decimal类型提升时高位会填充符号位因此 i 的值为 0xFFFFFFD2 第三个输出结果ffffffd2 // 赋值兼容转换 Shape Sh1; Rect1.name RECT; Sh1 Rect1; Shape* ptr Sh1; Shape ref Sh1; ptr-name x; ref.name x; Rect1.PrintName(); Sh1.PrintName(); cout endl;两次打印结果如下 RECT RECTxx对象的赋值是拷贝赋值 Rect1 和 Sh1 是两个独立的对象 由于 Sh1 是 Rect1 的副本对 Sh1 的修改不会影响 Rect1反之亦然。 4 继承的作用域 各作用域的影响 作用域语法编译查找规则生命周期局部域✅✅全局域✅✅命名空间域默认不查找除非展开或指定✅不存在类域✅不存在 4.1 示例1 class Person { protected:string _name 小李子; // 姓名int _num 111; // 身份证号 };class Student : public Person { public:void Print(){cout 姓名: _name endl;cout 学号: _num endl;// Student的_num和Person的_num构成隐藏关系cout 身份证号: Person::_num endl;} protected:int _num 999; // 学号 };void TestStu() {Student s1;s1.Print(); };姓名:小李子 学号:999 身份证号:111 4.2 示例2 class A { public:void ft() {cout void ft() endl;} };class B :public A { public:void ft(int i) {A::ft();cout void ft(int i), i i endl;} };void TestB() {B b;b.ft(1);// Q重载隐藏编译报错运行报错// A两者构成隐藏函数重载的前提是在同一个作用域 }void ft() void ft(int i), i 1 变式 class A { public:void ft() {cout void ft() endl;} };class B :public A { public:void ft(int i) {cout void ft(int i), i i endl;} };void TestB() {B bb;bb.ft();// Q重载隐藏重写编译报错运行报错不定项选择// A两者构成隐藏且编译报错// 如何调用父类b2.A::ft(); }5 继承过程中涉及的构造、拷贝构造和析构函数的工作机制 5.1 构造函数在继承中的作用和调用顺序 5.1.1 构造函数的调用顺序 当创建派生类对象时基类的构造函数会先于派生类的构造函数被调用。这是因为派生类需要依赖基类的成员和功能所以必须先初始化基类部分。 在构造派生类对象时不能先初始化派生类再初始化基类因为派生类的构造函数可能依赖于基类的成员。如果基类未先初始化这些成员将包含随机值从而导致不确定的行为。 示例 #include iostream using namespace std;class Base { public:Base() {cout Base Default Constructor endl;} };class Derived : public Base { public:Derived() {cout Derived Default Constructor endl;} };int main() {Derived d;return 0; }输出 Base Default Constructor Derived Default Constructor解释 基类成员当成一个整体在构造派生类对象时基类部分被当作一个整体调用其默认构造函数来初始化。派生类自己的成员 内置类型成员根据编译器的实现可能会自动初始化如置零也可能不处理产生未定义的值。自定义类型成员会调用它们的默认构造函数进行初始化。
5.1.2 派生类构造函数如何初始化基类 如果基类没有默认构造函数或者需要传递参数可以在派生类的构造函数的初始化列表中显式调用基类的构造函数。 示例 class Base { public:int baseValue;Base(int x) : baseValue(x) {cout Base Parameterized Constructor endl;} };class Derived : public Base { public:int derivedValue;Derived(int x, int y) : Base(x), derivedValue(y) {cout Derived Parameterized Constructor endl;} };解释 派生类的构造函数在初始化列表中调用了基类的构造函数 Base(x)并初始化了自己的成员 derivedValue(y)。 5.2 拷贝构造函数在继承中的行为 5.2.1 默认拷贝构造函数的生成 当你没有显式定义拷贝构造函数时编译器会为你生成一个默认拷贝构造函数。对于派生类默认拷贝构造函数的行为如下 基类成员当成一个整体调用基类的拷贝构造函数来复制基类部分的数据。派生类自己的成员 内置类型成员逐个成员进行值拷贝浅拷贝。自定义类型成员调用它们的拷贝构造函数进行复制。
示例 class Base { public:int baseValue;Base(int x) : baseValue(x) {}Base(const Base other) : baseValue(other.baseValue) {cout Base Copy Constructor endl;} };class Derived : public Base { public:int* derivedValue;Derived(int x, int y) : Base(x) {derivedValue new int(y);}// 默认拷贝构造函数// Derived(const Derived other) : Base(other), derivedValue(other.derivedValue) {}~Derived() {delete derivedValue;} };当我们执行以下代码 Derived d1(10, 20); Derived d2 d1; // 调用默认拷贝构造函数可能的问题 derivedValue 是一个指针默认拷贝构造函数会进行浅拷贝即复制指针的值。这会导致 d1 和 d2 的 derivedValue 指向同一块内存可能在析构时造成重复释放double free等错误。 5.2.2 需要自定义拷贝构造函数的情况 当派生类的成员涉及到动态内存分配或需要深拷贝时必须自定义拷贝构造函数。 示例自定义拷贝构造函数 class Derived : public Base { public:int* derivedValue;Derived(int x, int y) : Base(x) {derivedValue new int(y);}Derived(const Derived other) : Base(other) { // 调用基类的拷贝构造函数derivedValue new int(other.derivedValue); // 深拷贝cout Derived Copy Constructor endl;}~Derived() {delete derivedValue;} };解释 基类成员当成一个整体在派生类的拷贝构造函数中显式调用了基类的拷贝构造函数 Base(other)。派生类自己的成员 内置类型成员如果有内置类型成员默认会进行值拷贝。自定义类型成员需要手动编写代码来实现深拷贝防止多个对象共享同一块内存。 5.3 析构函数在继承中的作用和调用顺序 5.3.1 析构函数的调用顺序 当销毁派生类对象时析构函数的调用顺序与构造函数相反 首先调用派生类的析构函数清理派生类特有的资源。然后调用基类的析构函数清理基类部分的资源。 示例 class Base { public:~Base() {cout Base Destructor endl;} };class Derived : public Base { public:~Derived() {cout Derived Destructor endl;} };int main() {Derived d;return 0; }输出 Derived Destructor Base Destructor解释 先销毁派生类部分释放派生类特有的资源。然后销毁基类部分确保对象的所有资源都被正确释放。 5.3.2 虚析构函数的重要性 在涉及多态的情况下如果你通过基类指针删除派生类对象基类的析构函数必须是虚函数virtual否则可能导致派生类的析构函数不被调用造成资源泄漏。 示例 class Base { public:virtual ~Base() {cout Base Destructor endl;} };class Derived : public Base { public:~Derived() {cout Derived Destructor endl;} };int main() {Base ptr new Derived();delete ptr; // 正确调用派生类和基类的析构函数return 0; }输出 Derived Destructor Base Destructor解释 基类的析构函数被声明为虚函数后delete 基类指针时会先调用派生类的析构函数再调用基类的析构函数。如果基类析构函数不是虚函数只会调用基类的析构函数派生类的资源可能得不到释放。 5.4 总结与注意事项 5.4.1 默认构造函数的行为 基类成员在派生类的构造过程中基类部分被当作一个整体调用基类的默认构造函数。派生类的内置类型成员编译器可能会自动初始化如置零也可能不处理这取决于编译器实现。派生类的自定义类型成员会调用它们的默认构造函数进行初始化。 5.4.2 默认拷贝构造函数的行为 基类成员调用基类的拷贝构造函数复制基类部分的数据。派生类的内置类型成员逐个成员进行值拷贝浅拷贝。派生类的自定义类型成员调用它们的拷贝构造函数。 5.4.3 何时需要自定义拷贝构造函数 当派生类的成员涉及到动态内存分配、文件句柄、网络连接等需要深拷贝的资源时必须自定义拷贝构造函数和赋值运算符以正确管理资源防止浅拷贝带来的问题。 5.4.4 赋值操作符的注意事项 类似于拷贝构造函数赋值操作符在默认情况下也会进行浅拷贝。如果涉及到需要深拷贝的成员应该自定义赋值操作符。 5.4.5 避免资源泄漏和悬垂指针 正确地管理对象的生命周期确保析构函数能被正确调用防止资源泄漏。注意浅拷贝带来的悬垂指针问题指针指向已被释放的内存。