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

网站优化流程过期网站查询

网站优化流程,过期网站查询,石家庄做外贸网站推广,自己做的网址危险网站1 继承 继承是面向对象编程的一个基本概念#xff0c;它允许一个类#xff08;派生类、子类#xff09;继承另一个类#xff08;基类、父类#xff09;的属性和方法。继承可以减少代码冗余#xff0c;提高代码重用性#xff0c;并且有助于创建更复杂的类结构。 1.1 继…1 继承 继承是面向对象编程的一个基本概念它允许一个类派生类、子类继承另一个类基类、父类的属性和方法。继承可以减少代码冗余提高代码重用性并且有助于创建更复杂的类结构。 1.1 继承的基本用法 要在派生类中继承基类只需在派生类定义的时候列出基类的名称并指定继承方式公有、保护或私有 class BaseClass { // 基类的成员 }; class DerivedClass : public BaseClass { // 派生类的成员 };在上面代码中Derived 类公有地继承了 Base 类。这意味着 Base 类中的公有成员和保护成员在 Derived 类中保持原有的访问权限公有和保护而 Base 类中的私有成员在 Derived 类中是不可访问的。 派生类是基类的一个特殊化版本。这意味着派生类拥有基类所有的属性和方法同时还可以定义自己的新属性和方法。这种关系通常被称为 “IS-A” 关系即派生类 “是一种” 基类。如下为样例代码 class BaseClass { public:int getVal(){return m_val;}protected:int m_val 0; };class DerivedClass : public BaseClass { public:void derivedFunc(){m_val 2; //OK拥有基类的属性m_derivedVal getVal(); //OK拥有基类的方法}private:int m_derivedVal 1; };在上面代码中继承类 DerivedClass 的成员函数 derivedFunc() 可以使用基类的属性和方法。 1.2 继承的类型 C支持三种继承方式 公有继承Public Inheritance 当使用公有继承时基类的公有成员和保护成员在派生类中保持原有的访问权限而基类的私有成员在派生类中是不可访问的。这是最常见的继承方式。如下为样例代码 class BaseClass { public:int getVal1(){return m_val1;}protected:int m_val1 0;private:int m_val2 0; };class DerivedClass : public BaseClass //公有继承 { public:DerivedClass(){m_val2 1; //错误基类的私有成员在派生类中是不可访问的} };DerivedClass derivedObj; int val1 derivedObj.getVal1(); //OK公有继承下基类的公有成员在派生类中是公有的外部可以访问 derivedObj.m_val1 1; //错误公有继承下基类的保护成员在派生类中是保护的外部不可以访问 保护继承Protected Inheritance 在保护继承中基类的公有成员和保护成员在派生类中变为保护成员而基类的私有成员在派生类中是不可访问的。如下为样例代码 class BaseClass { public:int getVal1(){return m_val1;}protected:int m_val1 0; };class DerivedClass : protected BaseClass //保护继承 { };DerivedClass derivedObj; int val1 derivedObj.getVal1(); //错误保护继承下基类的公有成员在派生类中是保护的外部不可以访问私有继承Private Inheritance 在私有继承中基类的公有成员和保护成员在派生类中变为私有成员而基类的私有成员在派生类中是不可访问的。如下为样例代码 class BaseClass { public:int getVal1(){return m_val1;}protected:int m_val1 0; };class DerivedClass : private BaseClass //私有继承 { };DerivedClass derivedObj; int val1 derivedObj.getVal1(); //错误私有继承下基类的公有成员在派生类中是私有的外部不可以访问继承方式比较 继承方式基类公有成员基类保护成员基类私有成员公有继承继承为公有成员继承为保护成员不继承保护继承继承为保护成员继承为保护成员不继承私有继承继承为私有成员继承为私有成员不继承 1.3 派生类的构造函数和析构函数 在派生类对象初始化时派生类的构造函数需要调用基类的构造函数来初始化基类部分。这可以通过成员初始化列表实现。在销毁派生类对象时派生类的析构函数会在派生类部分析构之后自动调用基类的析构函数。 注意创建对象时先调用基类的构造函数再调用派生类的构造函数销毁对象时先调用派生类的析构函数再调用基类的析构函数。 1.3.1 派生类的构造函数 派生类的构造函数负责初始化从基类继承的成员和派生类自己新增的成员。在没有显式的指定基类构造函数的情况下派生类的构造函数会默认调用基类的无参构造函数来初始化基类部分。如下为样例代码 #include iostream class BaseClass { public:BaseClass(){printf(call BaseClass()\n);}BaseClass(int val){printf(call BaseClass(int val)\n);} };class DerivedClass : public BaseClass { public:DerivedClass(){printf(call DerivedClass()\n);}DerivedClass(int val){printf(call DerivedClass(int val)\n);} };int main() {DerivedClass derivedObj(2);return 0; }上面代码的输出为 call BaseClass() call DerivedClass(int val)在这个例子中DerivedClass 类继承自 BaseClass 类。DerivedClass 类与 BaseClass 类包含两个构造函数无参构造函数以及有参数构造函数。在 main 函数中创建 DerivedClass 类的对象时由于传入了参数 2 所以调用的是其有参数构造函数但是因为没有显式的指定基类构造函数所以会默认的调用基类的无参构造函数即使基类也有一个相似的有参数构造函数。 如果需要调用基类的有参数构造函数则需要做如下修改这也是常用的调用方式 #include iostream class BaseClass { public:BaseClass(){printf(call BaseClass()\n);}BaseClass(int val){printf(call BaseClass(int val)\n);} };class DerivedClass : public BaseClass { public:DerivedClass(){printf(call DerivedClass()\n);}DerivedClass(int val) : BaseClass(val) //这里显式的调用了基类的有参数构造函数{printf(call DerivedClass(int val)\n);} };int main() {DerivedClass derivedObj(2);return 0; }上面代码的输出为 call BaseClass(int val) call DerivedClass(int val)1.3.2 派生类的析构函数 在C中派生类的析构函数用于执行派生类对象在销毁时所需的清理工作。当派生类对象被销毁时它的析构函数首先执行然后是它的基类的析构函数。这是为了确保派生类中的成员在基类之前被正确释放。 如果没有在派生类中定义析构函数编译器会自动生成一个默认的析构函数。这个默认的析构函数会调用基类的析构函数如果基类有定义的话。如下为样例代码 #include iostream class BaseClass { public:BaseClass() {}~BaseClass(){printf(call ~BaseClass()\n);} };class DerivedClass : public BaseClass { public:DerivedClass() {}~DerivedClass(){printf(call ~DerivedClass()\n);} };int main() { {DerivedClass derivedObj;}return 0; }上面代码的输出为 call ~DerivedClass() call ~BaseClass()在上面代码中当 DerivedClass 类的对象被销毁时离开作用域后被销毁首先会调用 DerivedClass 类的析构函数然后是 BaseClass 类的析构函数。这样确保了派生类中的资源在基类之前被正确释放。 通常如果在派生类中分配了动态内存例如使用 new则应该在派生类的析构函数中释放这些内存。如果基类也分配了动态内存那么基类的析构函数应该负责释放这些内存。这样当派生类对象被销毁时所有的资源都会被正确清理。 1.4 多重继承 多重继承是指一个类可以继承自多个基类。这意味着一个类可以获取多个基类的属性和方法。然而多重继承也带来了一些复杂性和潜在的问题如菱形继承、二义性调用和初始化顺序等。 多重继承的简单使用如下 class BaseClass1 { protected:int m_baseClass1Val; };class BaseClass2 { protected:int m_baseClass2Val; };class DerivedClass : public BaseClass1, public BaseClass2 { public:void derivedFunc() {m_baseClass1Val 1; // 拥有 BaseClass1 基类的成员变量m_baseClass2Val 2; // 拥有 BaseClass2 基类的成员变量} };注意这里的 public、 protected 或 private 关键字决定了基类成员在派生类中的访问权限。 1.4.1 菱形继承 菱形继承 Diamond Inheritance 是C多重继承中的一个特定情况它指的是当一个类从两个或更多的类继承而这些类又有一个共同的基类时形成的继承结构图看起来像一个菱形。这种情况下基类在继承层次中被共享可能会导致一些问题特别是当基类包含数据成员时。 在C中菱形继承的主要问题在于基类数据成员的多份拷贝。如下为样例代码 class BaseClass { protected:int m_baseVal; };class BaseLeftClass : public BaseClass { };class BaseRightClass : public BaseClass { };class DerivedClass : public BaseLeftClass, public BaseRightClass { };在这个例子中DerivedClass 类通过 BaseLeftClass 和 BaseRightClass 间接地继承了两次 BaseClass 类。如果没有特殊处理BaseClass 类中的成员变量 m_baseVal 将在 DerivedClass 类中存在两份拷贝一份来自 BaseLeftClass一份来自 BaseRightClass。这不仅浪费空间而且可能导致逻辑错误因为通过 BaseRightClass 和 BaseRightClass 访问到的成员变量 m_baseVal 可能是不同的。 为了解决这个问题C 提供了虚继承Virtual Inheritance。虚继承确保在继承层次中无论基类出现多少次都只会存在一份基类子对象的拷贝。使用虚继承上面的例子可以改写为 class BaseClass { protected:int m_baseVal; };class BaseLeftClass : virtual public BaseClass { };class BaseRightClass : virtual public BaseClass { };class DerivedClass : public BaseLeftClass, public BaseRightClass { };通过使用 virtual public 的虚继承方式保证了在 DerivedClass 类中只有一个 BaseClass 子对象的拷贝。这消除了数据冗余并确保了通过 BaseLeftClass 和 BaseRightClass 访问到的 value 是同一个。 1.4.2 二义性调用 二义性调用发生在多重继承的情况下当派生类试图调用从多个基类继承而来的同名成员如方法或属性时编译器无法确定应该使用哪个基类的成员。 这种情况通常发生在以下场景中 1当派生类继承自两个基类并且这两个基类都有一个同名的成员函数。 3当派生类继承自一个基类并且这个基类继承自另外两个也拥有同名成员函数的基类。 如果派生类试图调用这个同名的成员函数编译器将无法确定应该使用哪个基类的版本因此会报错。如下为样例代码 #include iostream class BaseClass1 { public:void func() {}; };class BaseClass2 { public:void func() {}; };class DerivedClass : public BaseClass1, public BaseClass2 { };int main() { DerivedClass* obj new DerivedClass;obj-func(); // 错误二义性调用 delete obj;obj nullptr;return 0; }在上面代码中DerivedClass 类从 BaseClass1 和 BaseClass2 继承而 BaseClass1 和 BaseClass2 都有一个名为 func 的成员函数。因此当试图在 DerivedClass 类的对象上调用 func 时编译器不知道应该调用 BaseClass1::func 还是 BaseClass2::func从而产生了二义性。使用作用域解析运算符 (::)可以解决上面的二义性调用的问题 obj-BaseClass1::func();2 多态 多态 Polymorphism 是面向对象编程的三大基本特性之一它允许我们使用相同的接口来表示不同类型的对象。在 C 中多态通常通过虚函数 virtual functions 和指针或引用来实现。 2.1 虚函数 虚函数是 C 中实现多态的关键机制。通过在基类的成员函数前加上 virtual 关键字可以将其声明为虚函数。当派生类重写 override 这个虚函数时就可以通过基类指针或引用来调用派生类的实现这就是所谓的动态绑定或运行时多态。与之相对应的是静态绑定即在使用父类指针或引用调用子类对象的成员函数时如果没有使用虚函数则会进行静态绑定从而只能调用父类的成员函数无法调用子类特有的成员函数。 虚函数的原理主要涉及虚函数表和虚函数指针 1虚函数表 当一个类含有至少一个虚函数时编译器会为这个类创建一个虚函数表 vtable 并在每个该类的对象中嵌入一个指向这个虚函数表的指针通常被称为 vptr 。 虚函数表是一个函数指针数组其中每个元素都是指向类中定义的虚函数的指针。每个类包括它的所有派生类都会有自己的虚函数表。当派生类重写基类的虚函数时派生类的虚函数表会包含指向这些重写函数的指针。 2虚函数指针 虚函数指针 virtual function pointer 简称为 vptr 是一个隐藏的成员变量它存在于包含至少一个虚函数的类的对象中。 vptr 指向一个虚函数表 vtable 该表包含了类中所有虚函数的地址。虚函数表是一个函数指针数组每个元素都指向一个虚函数的实现。 vptr 的存在是实现多态性的关键它允许程序在运行时动态地确定应该调用哪个类的虚函数实现。当通过基类指针或引用调用一个虚函数时实际调用的是 vptr 所指向的虚函数表中的函数。 虚函数的具体工作原理如下 1定义虚函数在基类中声明一个或多个虚函数。 2创建虚函数表编译器为包含虚函数的类创建一个虚函数表。这个表是一个函数指针数组每个元素指向类中的一个虚函数。 3初始化虚函数指针当创建类的对象时编译器会为该对象的虚函数指针成员变量分配内存并初始化虚函数指针以指向该类的虚函数表。 4动态绑定当通过基类指针或引用调用虚函数时程序会查找虚函数指针所指向的虚函数表并调用表中对应的函数。这个查找过程是在运行时进行的因此被称为动态绑定。 注意点 虚函数表与虚函数指针都是由是编译器实现对程序员是透明的。 虚函数表与虚函数指针的存在对内存与性能有一定影响因为当创建类的对象时编译器会为该对象的虚函数指针成员变量分配内存并且每次调用虚函数都需要查找虚函数表。然而这种性能开销通常是可以接受的因为它提供了强大的多态性支持。 2.2 多态的使用 C中的多态主要有两种类型静态多态和动态多态。 静态多态 也称为编译时多态或早绑定 Early Binding 。这主要通过函数重载 Function Overloading 和模板 Templates 来实现。在编译时编译器就能确定应该调用哪个函数。 动态多态 也称为运行时多态或晚绑定 Late Binding 。这是通过虚函数 Virtual Functions 和继承来实现的。动态多态也被称为函数重写 Function Overriding 。在运行时程序根据对象的实际类型来确定应该调用哪个函数。 如下为样例代码 #include iostream class BaseClass { public:void overloadFunc(){printf(BaseClass overloadFunc()\n);}virtual void overrideFunc(){printf(BaseClass overrideFunc()\n);} };class DerivedClass : public BaseClass { public:void overloadFunc() // 函数重载{printf(DerivedClass overloadFunc()\n);}void overrideFunc() // 函数重写{printf(DerivedClass overrideFunc()\n);} };int main() { BaseClass* obj new DerivedClass;obj-overloadFunc(); // 调用基类的函数((DerivedClass*)obj)-overloadFunc(); // 强制类型转换后调用继承类的重载函数obj-overrideFunc(); // 调用继承类的重写函数delete obj;obj nullptr;return 0; }上面代码的输出为 BaseClass overloadFunc() DerivedClass overloadFunc() DerivedClass overrideFunc()在上面代码中 BaseClass 是一个基类它有一个成员函数 overloadFunc() 以及一个虚函数 overrideFunc()。 DerivedClass 是 BaseClass 的派生类它重载了 overloadFunc() 函数并且重写了 overrideFunc() 函数。在 main 函数中使用 BaseClass 基类的指针变量创建了一个 DerivedClass 派生类的对象并调用其 overloadFunc() 以及 overrideFunc()注意使用强制类型转换后才能真正调用到继承类的重载函数而重写函数则可以直接调用。 2.3 多态与构造函数、析构函数 构造函数不能被定义为虚函数 原因主要有以下几点 1执行时机构造函数在对象创建时立即执行它是对象初始化的一部分。而虚函数是在运行时通过动态绑定来确定的这需要对象的虚函数表已经初始化。在构造函数执行时虚函数表尚未建立因此无法执行虚函数。 2对象完整性在构造函数执行期间对象还没有完全构造完成。如果构造函数是虚函数那么当派生类的构造函数被调用时它的基类部分可能还没有完全初始化。这会导致对象的状态不一致进而引发错误。 3初始化顺序在继承层次中派生类构造函数在调用自身之前会首先调用基类的构造函数。如果基类构造函数是虚函数则会去查找派生类的重写虚函数从而导致初始化顺序的混乱。 建议将基类的析构函数定义为虚函数 将析构函数定义为虚函数是一个重要的代码构建技术点特别是在设计基类时。这是因为在多态性的场景中当使用基类指针或引用指向派生类对象时如果没有虚析构函数可能会导致派生类对象的析构过程不完整从而引发资源泄漏和其他问题。 当基类的析构函数不是虚函数时如果通过基类指针删除派生类对象只会调用基类的析构函数而不会调用派生类的析构函数。这会导致派生类对象中的资源如动态分配的内存没有被正确释放从而产生资源泄漏。 通过将基类的析构函数声明为虚函数可以确保当使用基类指针或引用删除派生类对象时派生类的析构函数也会被调用。这是多态性的一个关键方面它允许在运行时确定应该调用哪个类的析构函数。 如下为样例代码 #include iostream class BaseClass { public:// 将析构函数声明为虚函数 virtual ~BaseClass(){printf(virtual ~BaseClass() \n);} };class DerivedClass : public BaseClass { public:~DerivedClass(){printf(virtual ~DerivedClass() \n);} };int main() { BaseClass* obj new DerivedClass;delete obj;obj nullptr;// 如果 BaseClass 的析构函数不是虚函数这里只会调用 BaseClass 的析构函数 // 而不会调用 DerivedClass 的析构函数导致资源泄漏。 // 如果 BaseClass 的析构函数是虚函数则会先调用 DerivedClass 的析构函数 // 然后调用 BaseClass 的析构函数确保资源被正确释放。 return 0; }上面代码的输出为 virtual ~DerivedClass() virtual ~BaseClass()在上面代码中BaseClass 类的析构函数被声明为虚函数。当通过基类指针 obj 删除派生类 DerivedClass 的对象时由于析构函数是虚函数所以会先调用 DerivedClass 的析构函数然后再调用 BaseClass 的析构函数。这样派生类中的资源能够被正确释放避免了资源泄漏。 因此通常建议在设计基类时将析构函数定义为虚函数以确保在删除派生类对象时能够正确地调用析构函数链。
http://www.zqtcl.cn/news/854884/

相关文章:

  • 手机网站建设进度环境设计排版素材网站
  • 网站开发众筹地推网推平台
  • 长沙互联网网站建设wordpress标签id在哪里修改
  • 企业网站的建设 摘要大连网站设计策划
  • 做房地产一级市场的看什么网站网络营销外包推广方式
  • 网站建设基本流程包括哪几个步骤网站建设策划书网站发布与推广
  • 徐州整站优化手机网页端
  • 深圳中瑞建设集团官方网站宁波seo快速优化教程
  • 福田网站制作哪家好昆山企业网站建设公司
  • wordpress快六安网站自然排名优化价格
  • 网站的线下推广怎么做的系统官网网站模板下载安装
  • 北京网站优化推广公司企业网站建设费怎么核算
  • 网站建设vps个人如何做网站推广
  • 小语种网站怎么设计网页制作公司 大连
  • 贵港市城乡住房建设厅网站菜鸟教程网站
  • 广州网站建设找哪家免费搭建网站的软件
  • 培训班管理系统 免费太原优化网站排名
  • 上海怎么做网站网站让图片充满屏幕怎么做
  • 哈尔滨营销网站建设wordpress 加载图片不显示
  • 电商网站功能结构图网站做中秋专题怎么弄
  • 深圳专业建站平台陕西省建设工程质量安全监督总站网站
  • 制作网页的网站的软件是用户反馈数据分析软件园
  • 南京 做网站seo查询网站
  • 卖高仿名牌手表网站共享wifi小程序搭建
  • c#网站开发模板想在意大利做购物网站
  • 2015做那些网站能致富60天做网站
  • 沈阳个人建站模板网站图片计时器怎么做
  • 福州定制网站开发北京排名seo
  • 地方门户网站开发方案长沙有哪个学校可以学网站建设
  • 建个购物网站水果建设网站前的市场分析