C++面向对象的特性,c++面向对象的概念

  C++面向对象的特性,c++面向对象的概念

  Yyds干货库存

  前言,作为面向对象的语言,继承这个特性是不可或缺的。这个博客内容丰富,介绍了很多部分。内容可能有点难,比较抽象。我已经给了你一张图供你理解。接下来,进入正片!

  开始发短信

  一、继承的概念和定义1.1继承(inheritance)机制的概念是面向对象编程使代码可重用的最重要手段,它允许程序员保护

  它在原有类特征的基础上,进行扩展,增加功能,从而产生一个新的类,称为派生类。继承了面向对象

  程序设计的层次结构反映了从简单到复杂的认知过程。我们以前接触的复用都是函数复用,如下

  它是类设计级别的重用。

  class Person { public:void Print(){ cout name: _ name endl;cout age: _ age endl;} protected:string _ name= Peter ;//name int _ age=18;//年龄};//继承后,父类的Person成员(成员函数成员变量)都会成为子类的一部分。这表明学生和教师重用Person的成员。//接下来,我们使用监控窗口查看学生和教师对象,可以看到变量的重用。调用Print查看成员函数的重用。班级学生:公众人物{ protected:int _ stuid;//学号};班主任:公众人物{ protected:int _ jobid;//工号};int main(){ Student s;t老师;s . Print();t . Print();返回0;}

  1.2继承定义1.2.1定义格式下面我们看到Person是父类,也称为基类。Student是一个子类,也称为派生类。

  1.2.2继承关系和访问限定符

  1.2.3更改继承基类成员访问模式的类成员/public如何继承protected继承私有继承基类的公共成员派生类的公共成员派生类的受保护成员派生类的私有成员派生类的受保护成员派生类的私有成员派生类的私有成员在派生类中不可见在派生类中不可见在派生类中不可见摘要:

  基类的私有成员在派生类中是不可见的,无论它们是如何被继承的。这里的不可见是指基类的隐私。

  一些成员仍然是从派生类对象继承的,但是派生类对象无论是在类内还是类外都受到语法限制。

  无法访问。不能在派生类中访问私有基类成员。如果基类成员不希望在类外被直接访问,则需要在

  如果派生类可以访问它,它就被定义为受保护的。可以看出,受保护的成员限定符是由于继承。总结了上面的实际表格后,我们会发现基类的私有成员在子类中是不可见的。基类的其他

  成员子类的访问模式==Min(基类中成员的访问限定符和继承模式),public protected private。然而,当使用关键字class时,默认继承方法是私有的,而当使用struct时,默认继承方法是公共的

  展示写出继承的最佳方式。在实践中,一般使用公共继承,很少使用并且不提倡受保护/私有继承。

  使用protected/private继承,因为protected/private继承的成员只能在派生类的类中。

  使用表面,延伸的维护在实践中不是很强。二、基类和派生类的对象赋值转换可以赋值给基类的对象/基类的指针/基类的引用。这里有个形象的说法叫切片。

  或者切。剪切派生类中隐含父类的部分,赋给过去。

  基类对象不能分配给派生类对象。

  基类的指针或引用可以通过强制类型转换赋给派生类的指针或引用。但必须是基类。

  的指针只有在指向派生类对象时才是安全的。

  类Person { protected:string _ name;//名称string _ sex//gender int _ age;//年龄};班级学生:公众人物{ public:int _ No;//学号};void Test(){ Student sobj;//1.子类对象可以赋给父类对象/指针/引用Person pobj=sobjPerson * pp=sobjPerson rp=sobj////2.不能将基类对象分配给派生类对象。//sobj=pobj;//3.基类的指针可以通过强制类型转换赋给派生类的指针pp=sobj学生* ps1=(学生*)PP;//这种情况是可以转换的。PS1-_ No=10;pp=pobj学生* ps2=(学生*)PP;//虽然这种情况可以转换,但是会有越界访问ps2- _No=10的问题;} int main(){ Test();返回0;}

  三。继承中的作用域在继承系统中,基类和派生类都有独立的作用域。子类和父类中存在同名成员,子类成员会阻止父类对同名成员的直接访问。这种情况叫做隐藏,

  也叫重新定义。(在子类成员函数中,可以使用基类:基类成员来显示访问。)需要注意的是,如果是成员函数的隐藏,只需要相同的函数名就可以构成隐藏。注意,在实践中,最好不要在继承系统中定义同名的成员。//学生的_num和人的_num形成隐藏关系。可见这段代码虽然可以运行,但是非常容易混淆Class Person { protected:string _ name=小李子;//name int _ num=111;//身份证号};类学生:public person { public:void print(){ cout name: _ name endl;Cout ID号: Person:_ num endl;Cout的学号: _ num endl} protected:int _ num=999;//学号};void Test(){ Student S1;s1。print();} int main(){ Test();返回0;}

  //B中的fun和a中的fun不构成重载,因为同一作用域//B中的fun和a中的fun不构成隐藏,满足相同函数名的成员函数构成隐藏。class A { public:void fun(){ cout func() endl;}};B类:public A { public:void fun(int I){ A:fun();cout func(int I)- I endl;}};void Test(){ B B;b . fun(10);} int main(){ Test();返回0;}

  四。派生类的默认成员函数6默认成员函数。“默认”是指我们不写,编译器会自动给我们生成一个。然后,在派生类中

  这些成员函数是如何产生的?

  派生类的构造函数必须调用基类的构造函数来初始化基类的那部分成员。如果基类没有默认值

  您必须在派生类的构造函数的初始化列表阶段显示调用。派生类的复制构造函数必须调用基类的复制构造函数才能完成基类的复制初始化。派生类的Operator=必须调用基类的operator=才能完成基类的复制。派生类的析构函数会自动调用基类的析构函数,在被调用后清理基类的成员。因为这是方法

  确保派生类对象首先清理派生类成员,然后清理基类成员的顺序。初始化派生类时,在调整派生类构造之前调用基类构造。对象销毁清理首先调用派生类的销毁,然后调整基类的销毁。因为后续的一些场景析构函数需要重写,重写的条件之一就是函数名相同(这个后面会多态)。然后编译器会把析构函数名特殊处理成destrutor(),这样当父析构函数不为虚时,子析构函数和父析构函数就形成了一种隐藏关系。

  class Person { public:Person(const char * name= Peter ):_ name(name){ cout Person() endl;} Person(const Person p):_ name(p . _ name){ cout Person(const Person p) endl;} Person operator=(const Person p){ cout Person operator=(const Person p) endl;如果(这个!=p)_ name=p . _ name;返回* this} ~ Person(){ cout ~ Person() endl;} protected:string _ name;//name };class Student:public Person { public:Student(const char * name,int num) : Person(name),_ num(num){ cout Student() endl;} Student(const Student s):Person(s),_ num(s . _ num){ cout Student(const Student s) endl;}学生运算符=(const Student s) { cout 学生运算符=(const Student s) endl;如果(这个!=s){ Person:operator=(s);_ num=s. _ num}返回*这个;} ~ Student(){ cout ~ Student() endl;} protected:int _ num;//学号};void Test(){学生s1(jack ,18);学生S2(S1);学生S3(‘玫瑰’,17);s1=s3} int main(){ Test();返回0;}

  构造派生类时,首先调用基类的构造函数来构造。程序完成后,准备进行资源清理。先调用派生类的析构函数,然后派生类的析构函数会调整基类的析构函数!

  5.继承和友元的关系是不能继承的,也就是说基类的友元不能访问子类的私有和受保护的成员。

  班级学生;class Person { public:friend void Display(const Person p,const Student s);protected:string _ name;//name };班级学生:公众人物{ protected:int _ stuNum;//学号};void Display(const Person p,const Student s){ cout p . _ name endl;cout s. _ stuNum endl} int main(){ Person p;学生s;显示(p,s);}

  不及物动词继承和静态成员的基类定义了一个静态成员,所以整个继承系统中只有一个这样的成员。无论派生出多少个孩子

  类中,静态成员只有一个实例。(所有基类和派生类共享这个静态成员变量!)

  class Person { public:Person(){ _ count;} protected:string _ name;//Name public:static int _ count;//数人数。};int Person:_ count=0;班级学生:公众人物{ protected:int _ stuNum;//学号};班级毕业:公派学生{ protected:string _ seminar course;//研究对象};void test person(){ Student S1;学生S2;学生S3;毕业S4;cout number: Person:_ count endl;学生:_ count=0;cout number: Person:_ count endl;} int main(){ test person();返回0;}

  每次创建派生类的对象,都会自动调试基类的构造函数,然后导致_ count因为所有继承系统都共享这个静态成员变量,所以任何对象的_count成员变量的值都是一样的!

  七。复菱形继承和菱形虚拟继承单继承:当一个子类只有一个直接父类时,这种继承关系称为单继承。

  多重继承:当一个子类有两个或多个直系父类时,这种继承关系称为多重继承。

  钻石继承:钻石继承是多重继承的特例。

  菱形继承:从下面的对象成员模型构造可以看出,菱形继承存在数据冗余和二义性的问题。

  助理对象中会有两个成员。

  class Person { public:string _ name;//name };班级学生:公众人物{ protected:int _ num;//学号};班主任:公众人物{ protected:int _ id;//员工号};助教:公学生,公老师{ protected:string _ major course;//专业课};Void Test(){ //这将是不明确的。无法知道访问的是哪个助手a;a._name=彼得;//你需要展示你指定访问的哪些父类成员可以解决二义性问题,但是数据冗余问题不能。a .学生:_ name= xxxa .老师:_ name= yyy}

  虚拟继承可以解决钻石继承的二义性。但是不能解决数据冗余的问题。如上面的继承关系,在学生和

  教师通过虚拟继承来继承人,可以解决这个问题。需要注意的是,虚拟传承不应该在其他地方。

  要使用的交易方。

  class Person { public:string _ name;//name };班级学生:虚拟公众人物{ protected:int _ num;//学号};班主任:虚拟公众人物{ protected:int _ id;//员工号};助教:公学生,公老师{ protected:string _ major course;//专业课};void Test(){ Assistant a;a._name=彼得;}

  为了研究虚拟继承的原理,我给出了一个简化的钻石继承系统,然后借助内存窗口观察对象成员的模型。

  虚拟继承之前

  虚拟继承后

  下图是一个菱形的虚拟继承内存对象成员模型:这里可以分析出A在D对象中被放在对象组成的最底层。

  面,这个A同时属于B和C,那么B和C如何找到共同的A呢?这里有B和C两个指针,分别指

  敬一张桌子。这两个指针称为虚拟基表指针,这两个表称为虚拟基表。存储在虚拟表中的偏移量。传递偏移

  你可以找到下面的A。

  从地址可以看出,虚拟继承后,代码中的派生类D只有一个_a。解决了数据的冗余。

  以下是上述人关系的钻石虚拟继承的原理解释:

  八。继承的总结和反思很多人说C语法复杂,其实多重继承就是一种表现。更有传承,有钻石传承,有凌。

  形状继承有菱形虚继承,底层实现非常复杂。所以一般不建议设计多继承,一定不要设置。

  计算钻石遗产。否则复杂度和性能都会有问题。多继承可以认为是c的缺陷之一,很多后来的OO语言,比如Java,都没有多继承。(本章结束!)

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • office2010激活密钥大全 怎么永久激活office2010
  • project2010产品密钥免费_project2010激活密钥永久激活码
  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • chatgpt是什么?为什么这么火?
  • ChatGPT为什么注册不了?OpenAI ChatGPT的账号哪里可以注册?
  • OpenAI ChatGPT怎么注册账号?ChatGPT账号注册教程
  • chatgpt什么意思,什么是ChatGPT ?
  • CAD中怎么复制图形标注尺寸不变,CAD中怎么复制图形线性不变
  • cad中怎么创建并使用脚本文件,cad怎么运行脚本
  • cad中快速计算器的功能,cad怎么快速计算
  • cad中快速修改单位的方法有哪些,cad中快速修改单位的方法是
  • cad中心点画椭圆怎么做,cad轴测图怎么画椭圆
  • CAD中常用的快捷键,cad各种快捷键的用法
  • 留言与评论(共有 条评论)
       
    验证码: