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

seo博客写作深圳网站关键字优化

seo博客写作,深圳网站关键字优化,html与wordpress,网站能不能自己做目录 C多态#xff1a;#xff1a; 多态的概念 多态的定义及实现 多态的构成条件 虚函数 虚函数的重写 虚函数重写的特例 C11 override和final 重载、重写重定义的对比 抽象类 概念 接口继承和实现继承 多态的原理 虚函数表 多态的原理 动态绑定和静态绑定 单继承和…目录 C多态 多态的概念 多态的定义及实现 多态的构成条件 虚函数 虚函数的重写 虚函数重写的特例 C11 override和final         重载、重写重定义的对比 抽象类 概念 接口继承和实现继承 多态的原理 虚函数表 多态的原理 动态绑定和静态绑定 单继承和多继承关系的虚函数表 单继承中的虚函数表 多继承中的虚函数表 继承和多态常见的面试问题 概念考察 问答题 C多态 多态的概念 多态就是函数调用的多种形态使用多态能够使得不同的对象去完成同一件事时产生不同的作用和结果。 例如在现实生活当中普通人买票是全价学生买票是半价而军人允许优先买票。不同身份的人去买票所产生的行为是不同的这就是所谓的多态。 多态的定义及实现 多态的构成条件 多态是指不同继承关系的类对象去调用同一函数产生了不同的行为。在继承中要想构成多态需要满足两个条件 1.必须通过基类的指针或者引用调用虚函数。 2.被调用的函数必须是虚函数且派生类必须对基类的虚函数进行重写。 虚函数 被virtual修饰的类成员函数被称为虚函数。 class Person { public://被virtual修饰的类成员函数virtual void BuyTicket(){cout 买票-全价 endl;} };需要注意的是 1.只有类的非静态函数前可以加virtual普通函数前不能加virtual。 2.虚函数这里的virtual和虚继承中的virtual是同一个关键字但是它们之间没有任何关系。虚函数这里的virtual是为了实现多态而虚继承的virtual是为了解决菱形继承的数据冗余和二义性。 虚函数的重写 虚函数的重写也叫做虚函数的覆盖若派生类中有一个和基类完全相同的虚函数(返回值类型相同、函数名相同以及参数列表完全相同)此时我们称该派生类的虚函数重写了基类的虚函数。 例如我们以下Student和Soldier两个子类重写了父类Person的虚函数。 class Person { public:virtual void BuyTicket(){cout 买票-全价 endl;} }; //父类 class Person { public:virtual void BuyTicket(){cout 买票-全价 endl;} }; //子类 class Student : public Person { public:virtual void BuyTicket(){cout 买票-半价 endl;} }; //子类 class Soldier : public Person { public:virtual void BuyTicket(){cout 优先-买票 endl;} };现在我们就可以通过父类Person的指针或者引用调用虚函数BuyTicket此时不同类型的对象调用的就是不同的函数产生的也是不同的结果进而实现了函数调用的多种形态。 void Func(Person p) {p.BuyTicket(); } void Func(Person* p) {p-BuyTicket(); } int main() {Person p; Student st; Soldier sd; Func(p); Func(st); Func(sd); Func(p); Func(st); Func(sd); return 0; } 虚函数重写的特例 协变基类与派生类虚函数的返回值类型不同 派生类重写基类虚函数时与基类虚函数返回值类型不同。同时基类虚函数返回基类对象的指针或者引用派生类虚函数返回派生类对象的指针或者引用称为协变。 例如下列代码中基类Person当中的虚函数fun的返回值类型是基类A对象的指针派生类Student当中的虚函数fun的返回值类型是派生类B对象的指针此时也认为派生类Student的虚函数重写了基类Person的虚函数。   //基类 class A {}; //子类 class B : public A {}; //基类 class Person { public://返回基类A的指针virtual A* fun(){cout A* Person::f() endl;return new A;} }; //子类 class Student : public Person { public://返回子类B的指针virtual B* fun(){cout B* Student::f() endl;return new B;} };此时我们通过父类Person的指针调用虚函数fun父类指针若指向的是父类对象则调用父类的虚函数父类指针若指向的是子类对象则调用子类的虚函数。 int main() {Person p;Student st;Person* ptr1 p;Person* ptr2 st;ptr1-fun(); ptr2-fun(); return 0; }析构函数的重写基类与派生类析构函数的名字不同 如果基类的析构函数为虚函数此时派生类析构函数只要定义无论是否加virtual关键字都与基类的析构函数构成重写虽然基类与派生类析构函数名字不同。 例如下面代码中父类Person和子类Student的析构函数构成重写。 //父类 class Person { public:virtual ~Person(){cout ~Person() endl;} }; //子类 class Student : public Person { public:virtual ~Student(){cout ~Student() endl;} };那父类和子类的析构函数构成重写的意义何在呢试想以下场景分别new一个父类对象和子类对象并均用父类指针指向它们然后分别用delete调用析构函数并释放对象空间。 int main() {//分别new一个父类对象和子类对象并均用父类指针指向它们Person* p1 new Person;Person* p2 new Student;//使用delete调用析构函数并释放对象空间delete p1;delete p2;return 0; }在这种场景下若是父类和子类的析构函数没有构成重写就可能会导致内存泄漏因为此时delete p1和delete p2都是调用的父类的析构函数而我们所期望的是p1调用父类的析构函数p2调用子类的析构函数即我们期望的是一种多态行为。 此时只有父类和子类的析构函数构成了重写才能使得delete按照我们的预期进行析构函数的调用才能实现多态。因此为了避免出现这种情况比较建议将父类的析构函数定义为虚函数。 知识扩展 在继承当中子类和的析构函数和父类的析构函数构成隐藏的原因就在这里这里表面上看子类的析构函数和父类的析构函数的函数名不同但是为了构成重写编译后析构函数的名字会被统一处理成destructor()。 C11 override和final 从上面可以看出C对函数重写的要求比较严格有些情况下由于疏忽可能会导致函数名的字母次序写反而无法构成重写而这种错误在编译期间是不会报错的直到在程序运行时没有得到预期结果再来进行调试会得不偿失因此C11提供了final和override两个关键字可以帮助用户检测是否重写。 final修饰虚函数表示该虚函数不能再被重写。 例如父类Person的虚函数BuyTicket被final修饰后就不能再被重写了子类若是重写了父类的BuyTicket函数则编译报错。 //父类 class Person { public:virtual void BuyTicket() final{cout 买票-全价 endl;} }; //子类 class Student : public Person { public:virtual void BuyTicket(){cout 买票-半价 endl;} }; //子类 class Soldier : public Person { public:virtual void BuyTicket(){cout 优先-买票 endl;} }; override检查派生类虚函数是否重写了基类的某个虚函数如果没有重写则编译报错。 例如子类Student和Soldier的虚函数BuyTicket被override编译时就会检查子类的这两个BuyTicket函数是否重写了父类的虚函数如果没有则会编译报错。 //父类 class Person { public:virtual void BuyTicket(){cout 买票-全价 endl;} }; //子类 class Student : public Person { public:virtual void BuyTicket() override{cout 买票-半价 endl;} }; //子类 class Soldier : public Person { public:virtual void BuyTicket(int i) override{cout 优先-买票 endl;} }; 重载、重写重定义的对比 抽象类 概念 在虚函数的后面加上0则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类)抽象类不能实例化出对象。 //抽象类接口类 class Car { public:virtual void Drive() 0; }; int main() {Car c; return 0; } 派生类继承抽象类后也不能实例化出对象只有重写纯虚函数派生类才能实例化出对象。 //抽象类接口类 class Car { public:virtual void Drive() 0; }; //派生类 class Benz : public Car { public:virtual void Drive(){cout Benz-舒适 endl;} }; //派生类 class BMV : public Car { public:virtual void Drive(){cout BMV-操控 endl;} }; int main() {Benz b1;BMV b2;Car* p1 b1;Car* p2 b2;p1-Drive(); p2-Drive(); return 0; }抽象类既然不能实例化出对象那抽象类存在的意义是什么? 1.抽象类可以更好的去表示现实的世界中没有实例对象对应的抽象类型比如植物、人、动物等。 2.抽象类很好的体现了虚函数的继承是一种接口继承强制子类去重写纯虚函数因为子类若是不重写冲父类继承下来的纯虚函数那么子类也是抽象类也不能实例化出对象。 接口继承和实现继承 实现继承普通函数的继承是哟中实现继承派生类继承了基类函数的实现可以使用该函数。 接口继承虚函数的继承是一种接口继承派生类继承的是基类虚函数的接口目的是为了重写达成多态。 建议如果不实现多态就不要把函数定义成虚函数。 虚函数表 下面是一道常考的笔试题Base类实例化出对象的大小是什么? class Base { public:virtual void Func1(){cout Func1() endl;} private:int _b 1; };通过观察测试我们发现Base类实例化的对象b的大小是8个字节。 b对象当中除了_b成员之外实际上还有一个_vfptr放在对象的里面对象中的这个指针叫做虚函数表指针简称虚表指针虚表指针指向一个虚函数表简称虚表每一个含有虚函数的类中都至少有一个虚表指针。 虚函数表中到底放的是什么? 下面Base类当中有三个成员函数其中Func1和Func2是虚函数Func3是普通成员函数子类Derive当中仅对父类的Func1函数进行了重写。 //父类 class Base { public://虚函数virtual void Func1(){cout Base::Func1() endl;}//虚函数virtual void Func2(){cout Base::Func2() endl;}//普通成员函数void Func3(){cout Base::Func3() endl;} private:int _b 1; }; //子类 class Derive : public Base { public://重写虚函数Func1virtual void Func1(){cout Derive::Func1() endl;} private:int _d 2; }; int main() {Base b;Derive d;return 0; }通过调试可以发现父类对象b和基类对象d当中除了自己的成员变量外父类和子类对象都有一个虚表指针分别指向属于自己的虚表。 实际上虚表当中存储的就是虚函数的地址因为Func1和Func2都是虚函数所以父类对象b的虚表当中存储的就是虚函数Func1和Func2的地址。 而子类虽然继承了父类的虚函数Func1和Func2但是子类对父类的虚函数Func1进行了重写因此子类对象d的虚表当中存储的是父类的虚函数Func2的地址和重写的Func1的地址。这就是为什么虚函数的重写也叫做覆盖覆盖就是指虚表中虚函数地址的覆盖重写是语法的叫法覆盖是原理层的叫法。 其次需要注意的是Func2是虚函数所以继承下来之后放进了子类的虚表而Fun3是普通成员函数继承下来后不会放进子类的虚表。此外虚函数表本质上是一个存放函数指针的指针数组一般情况下会在这个数组最后放一个nullptr。 总结一下派生类的虚表生成步骤如下 1.先将基类中的虚表内容拷贝一份到派生类的虚表。 2.如果派生类重写了基类中的某个虚函数则用派生类自己的虚函数地址覆盖虚表中基类的虚函数地址。 3.派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。 虚表是什么阶段初始化的? 虚函数存在哪里?虚表存在哪里? 虚表实际上是在构造函数初始化列表阶段初始化的注意虚表当中存的是虚函数的地址不是虚函数虚函数和普通函数一样都是存在代码段的只是它的地址存到了虚表当中。另外对象中存的不是虚表而是指向虚表的指针。 至于虚表是存在哪里的我们可以通过以下这段代码进行判断。 代码当中打印了对象b当中的虚表指针也就是虚表的地址可以发现虚表地址与代码段的地址非常接近由此我们可以得出虚表实际上是存在代码段的。 多态的原理 例如下面代码中为什么当父类Person指针指向的是父类对象Mike时调用的就是父类的BuyTicket当父类Person指针指向的时子类对象Johnson时调用的就是子类的BuyTicket? 通过调试可以发现对象Mike中包含一个成员变量_p和一个虚表指针对象Johnson中包含两个成员变量_p和_s以及一个虚表指针这两个对象当中的虚表指针分别指向自己的虚表 围绕此图分析便可得到多态的原理 1.父类指针p1指向Mike对象p1-BuyTicket在Mike的虚表中找到的虚函数就是Person::BuyTicket。 2.父类指针p2指向Johnson对象p2-BuyTicket在Johnson的虚表中找到的虚函数就是Student::BuyTicket。 这样就实现出了不同对象去完成同一行为时展现出不同的形态。 现在想想多态构成的两个条件一是完成虚函数的重写二是必须使用父类的指针或者引用去调用虚函数。必须完成虚函数的重写是因为我们需要完成子类虚表当中虚函数地址的覆盖那么为什么必须使用父类的指针或者引用去调用虚函数呢?为什么使用父类对象去调用虚函数达不到多态的效果呢? Person p1 Mike; Person p2 Johnson; 使用父类对象时切片得到部分成员变量后会调用父类的拷贝构造函数对那部分成员变量进行拷贝构造而拷贝构造出来的父类对象p1和p2当中的虚表指针指向的都是父类对象的虚表因为同类型的对象共享一张虚表它们的虚表指针指向的虚表时一样的。 因此我们后序用p1和p2调用虚函数时p1和p2通过虚表指针找到的虚表是一样的最终调用的函数也是一样的也就无法构成多态。 总结 1.构成多态只想谁就调用谁的虚函数跟指向的对象有关 2.不构成多态对象类型是什么就调用谁的虚函数跟类型有关 动态绑定和静态绑定 静态绑定静态绑定又称为前期绑定(早绑定)在程序编译期间确定了程序的行为也称为静态多态比如函数重载。 动态绑定”动态绑定又称为后期绑定(晚绑定)在程序运行期间根据具体拿到的类型确定程序的具体行为调用具体的函数也称为动态多态。 我们可以通过查看汇编的方式进一步理解静态绑定和动态绑定。 //父类 class Person { public:virtual void BuyTicket(){cout 买票-全价 endl;} }; //子类 class Student : public Person { public:virtual void BuyTicket(){cout 买票-半价 endl;} }; 我们若是按照如下方式调用BuyTicket函数则不构成多态函数的调用是在编译时确定的。 int main() {Student Johnson;Person p Johnson; //不构成多态p.BuyTicket();return 0; }将调用函数的那句代码翻译成汇编就只有以下两条汇编语句也就是直接调用的函数。 而我们若是按照如下方式调用BuyTicket函数则构成多态函数的调用是在运行时确定的。 相比不构成多态时的代码构成多态时调用函数的那句代码翻译成汇编后就变成了8条汇编指令主要原因就是我们需要在运行时先到指定对象的虚表中找到要调用的虚函数然后才能进行函数的调用。这样就很好的体现可静态绑定是在编译时确定的而动态绑定是在运行时确定的。 单继承和多继承关系的虚函数表 单继承中的虚函数表 以下列单继承关系为例我们来看看基类和派生类的虚表模型。 //基类 class Base { public:virtual void func1() {cout Base::func1() endl; }virtual void func2() { cout Base::func2() endl; } private:int _a; }; //派生类 class Derive : public Base { public:virtual void func1() { cout Derive::func1() endl; }virtual void func3() { cout Derive::func3() endl;}virtual void func4(){ cout Derive::func4() endl; } private:int _b; };其中基类和派生类的虚表模型如下 在单继承关系当中派生类的虚表生成过程如下 1.继承基类的虚表内容到派生类的虚表。 2.对派生类重写了的虚函数地址进行覆盖比如func1。 3.虚表当中新增派生类当中新的虚函数地址比如func3和func4。 在调试过程中某些编译器的监视窗口当中看不到虚表的当中的func3和func4可能是编译器的监视窗口故意隐藏了这两个函数此时如果我们想要看到派生类对象完整的虚表有两个方法。 一、使用内存监视窗口 使用内存监视窗口看到的内容是最真实的我们调出内存监视窗口然后输入派生类对象当中的虚表指针即可看到虚表当中存储的虚函数。 二、使用代码打印虚表内容 我们可以使用以下代码打印上述基类和派生类对象虚表内容在打印过程中可以顺便用虚函数地址调用对应的虚函数从而打印出虚函数的函数名这样可以进一步确定虚表当中存储的是哪一个函数的地址。 typedef void(*VFPTR)(); void PrintVFT(VFPTR* ptr) {printf(虚表地址:%p\n, ptr);for (int i 0; ptr[i] ! nullptr; i){printf(ptr[%d]:%p--, i, ptr[i]); ptr[i](); }printf(\n); } int main() {Base b;PrintVFT((VFPTR*)(*(int*)b)); Derive d;PrintVFT((VFPTR*)(*(int*)d)); return 0; }多继承中的虚函数表 以下列多继承关系为例我们来看看基类和派生类的虚表模型。 //基类1 class Base1 { public:virtual void func1() {cout Base1::func1() endl;}virtual void func2() {cout Base1::func2() endl;} private:int _b1; }; //基类2 class Base2 { public:virtual void func1() { cout Base2::func1() endl;}virtual void func2() {cout Base2::func2() endl;} private:int _b2; }; //多继承派生类 class Derive : public Base1, public Base2 { public:virtual void func1() { cout Derive::func1() endl;}virtual void func3() { cout Derive::func3() endl;} private:int _d1; };其中两个基类的虚表模型如下 派生类的虚表模型如下 在多继承关系当中派生类的虚表生成过程如下 1.分别继承各个基类的虚表内容到派生类的各个虚表当中。 2.对派生类重写了的虚函数地址进行覆盖。 3.在派生类第一个继承基类部分的虚表当中新增派生类当中新的虚函数地址。 这里在调试时在某些编译器下也会出现显示不全的问题此时如果我们想要看到派生类对象完整的虚表也是用那两种方法。 一、使用内存监视窗口 二、使用代码打印虚表内容 需要注意的是我们在派生类第一个虚表地址的基础上向后移sizeof(Base1)个字节即可得到第二个虚表的地址。 为什么重写之后第一张和第二张虚表里面的func1虚函数地址不一样? 实际上内存里面只有一份被重写的虚函数func1重写之后Base1虚表里的func1正好被覆盖但是Base2里面的虚表的func1也要被覆盖所以如果是Base2类型指针多态调用func1时它会先调用一个被封装好的函数这个函数内部会先做指针的偏移将指针的地址进行-8让指针指向第一张虚表的的func1虚函数然后调用这份真正被重写的虚函数所以第二张虚表里面看起来被重写的func1并不是内存里真正的func1而是被封装后的func1间接调用内存里只有一份的虚函数。 继承和多态常见的面试问题 概念考察 1、下面哪种面向对象的方法可以让你变得富有 A.继承 B.封装 C.多态 D.抽象 答案A 2、是面向对象程序设计语言中的一种机制这种机制实现了方法的定义与具体的对象无关而方法的调用则可以关联于具体的对象。 A.继承 B.模板 C.对象的自身引用 D.动态绑定 答案D 3.关于面向对象设计中的继承和组合下面说法错误的是 A.继承允许我们覆盖重写父类的实现细节父类的实现对于子类是可见的是一种静态复用也称为白盒复用。 B.组合的对象不需要关系各自的实现细节之间的关系是在运行时候才确定的是一种动态复用也称为黑盒复用。 C.优先使用继承而不是组合是面向对象设计的第二原则。 D.继承可以使子类能自动继承父类的接口但在设计模式中认为这是一种破坏了父类的封装性的表现。 答案C 4、以下关于纯虚函数的说法正确的是 A.声明纯虚函数的类不能实例化对象 B.声明纯虚函数的类是虚基类 C.子类必须实现基类的纯虚函数 D.纯虚函数必须是空函数 答案A 5、关于虚函数的描述正确的是 A.派生类的虚函数与基类的虚函数具有不同的参数个数和类型 B.内联函数不能是虚函数 C.派生类必须重新定义基类的虚函数 D.虚函数可以是一个static型的函数 答案B 6、关于虚表的说法正确的是 A.一个类只能有一张虚表 B.基类中有虚函数如果子类中没有重写基类的虚函数此时子类与基类共用同一张虚表 C.虚表是在运行期间动态生成的 D.一个类的不同对象共享该类的虚表 答案D 7、假设A类中有虚函数B继承自AB重写A中的虚函数也没有定义任何虚函数则 A.A类对象的前4个字节存储虚表地址B类对象的前4个字节不是虚表地址 B.A类对象和B类对象前4个字节存储的都是虚基表的地址 C.A类对象和B类对象前4个字节存储的虚表地址相同 D.A类和B类虚表中虚函数个数相同但A类和B类使用的不是同一张虚表 答案D 8、下面程序输出结果是什么 #include iostream using namespace std; class A { public:A(char* s) { cout s endl; }~A() {}; }; class B : virtual public A { public:B(char* s1, char* s2):A(s1){cout s2 endl;} }; class C : virtual public A { public:C(char* s1, char* s2):A(s1){cout s2 endl;} }; class D : public B, public C { public:D(char* s1, char* s2, char* s3, char* s4):B(s1, s2), C(s1, s3), A(s1){cout s4 endl;} }; int main() {D* p new D(class A, class B, class C, class D);delete p;return 0; }A.class A class B class C class D B.class D class B class C class A C.class D class C class B class A D.class A class C class C class D 答案A 9、下面说法正确的是多继承中指针的偏移问题 class Base1 { public:int _b1; }; class Base2 { public:int _b2; }; class Derive : public Base1, public Base2 { public:int _d; }; int main() {Derive d;Base1* p1 d;Base2* p2 d;Derive* p3 d;return 0; }A.p1 p2 p3 B.p1 p2 p3 C.p1 p3 ! p2 D.p1 ! p2 ! p3 答案C 10、以下程序输出结果是什么 #include iostream using namespace std; class A { public:virtual void func(int val 1){cout A- val endl;}virtual void test(){func();} }; class B : public A { public:void func(int val 0){cout B- val endl;} }; int main() {B* p new B;p-test();return 0; }A.A-0 B.B-1 C.A-1 D.B-0 E.编译错误 F.以上都不正确 答案B 问答题 1、什么是多态 多态是指不同继承关系的类对象去调用同一函数产生了不同的行为。多态又分为静态的多态和动态的多态 2、什么是重载、重写、重定义 重载是指两个函数在同一作用域这两个函数的函数名相同参数不同。 重写(覆盖)是指两个函数分别在基类和派生类的作用域这两个函数的函数名、参数、返回值都必须相同(协变例外)且这两个函数都是虚函数。 重定义(隐藏)是指两个函数分别在基类和派生类的作用域这两个函数的函数名相同。若两个基类和派生类的同名函数不构成重写就是重定义。   3、多态的实现原理 构成多态的父类对象和子类对象的成员当中都包含一个虚表指针这个虚表指针指向一个虚表虚表当中存储的是该类对应的虚函数地址。因此当父类指针指向父类对象时通过父类指针找到虚表指针然后在虚表当中找到的就是父类当中对应的虚函数当父类指针指向子类对象时通过父类指针找到虚表指针然后在虚表当中找到的就是子类当中对应的虚函数。   4、inline函数可以是虚函数吗 我们知道内联函数是会在调用的地方展开的也就是说内联函数是没有地址的但是内联函数是可以定义成虚函数的当我们把内联函数定义虚函数后编译器就忽略了该函数的内联属性这个函数就不再是内联函数了因为需要将虚函数的地址放到虚表中去。 5、静态成员函数可以是虚函数吗 静态成员函数不能是虚函数因为静态成员函数没有this指针使用类型::成员函数的调用方式无法访问虚表所以静态成员函数无法放进虚表。 6、构造函数可以是虚函数吗 构造函数不能是虚函数因为对象中的虚表指针是在构造函数初始化列表阶段才初始化的 7、析构函数可以是虚函数吗什么场景下析构函数是虚函数 析构函数可以是虚函数并且最后把基类的析构函数定义成虚函数。若是我们分别new一个父类对象和一个子类对象并均用父类指针指向它们当我们使用delete调用析构函数并释放对象空间时只有当父类的析构函数是虚函数的情况下才能正确调用父类和子类的析构函数分别对父类和子类对象进行析构否则当我们使用父类指针delete对象时只能调用到父类的析构函数。   8、对象访问普通函数快还是虚函数更快 对象访问普通函数比访问虚函数更快若我们访问的是一个普通函数那直接访问就行了但当我们访问的是虚函数时我们需要先找到虚表指针然后在虚表当中找到对应的虚函数最后才能调用到虚函数。 9、虚函数表是在什么阶段生成的存在哪 虚表是在构造函数初始化列表阶段进行初始化的虚表一般情况下是存在代码段(常量区)的。 10、C菱形继承的问题虚继承的原理 菱形虚拟继承因为子类对象当中会有两份父类的成员因此会导致数据冗余和二义性的问题。 虚继承对于相同的虚基类在对象当中只会存储一份若要访问虚基类的成员需要通过虚基表获取到偏移量进而找到对应的虚基类成员从而解决了数据冗余和二义性的问题。 11.什么是抽象类抽象类的作用 抽象类很好的体现了虚函数的继承是一种接口继承强制子类去抽象纯虚函数因为子类若是不抽象从父类继承下来的纯虚函数那么子类也是抽象类也不能实例化出对象。其次抽象类可以很好的去表示现实世界中没有示例对象对应的抽象类型比如植物、人、动物等。
http://www.pierceye.com/news/563128/

相关文章:

  • 怎么知道一个网站是谁做的建筑认证
  • 网站关键词优化排名公司网站备案的意思
  • 怎么把qq空间做成企业网站医疗网站设计
  • 个人博客网站需求分析上海最大企业前十名
  • 兴义之窗网站怎么做网页界面设计的类别
  • 黄南州网站建设公司安徽省建设厅执业资格注册中心网站
  • wordpress布置网站教程wordpress it模板下载地址
  • 网站首页栏目设置宿州建设网站公司哪家好
  • 西安网站建设怎么接单做社交的招聘网站
  • 实训课网站开发个人小结横岗做网站
  • 网站集约化建设管理方案wordpress加cnzz统计在那里加
  • 重庆知道推广网站方法青岛网络推广的有哪些公司
  • 自己做网站服务器要多少钱特殊字体
  • 网站建设合同 协议书网站建设工具有哪些
  • 网站建设的基本条件网站建设策划案怎么写
  • 知乎网站开发用的语言郑州建设网站哪家好
  • 企业官网建站费用长沙做无痛肠镜东大医院l网站
  • 建网站资料wordpress 读书模板
  • 网站建设初学者教程成华区微信网站建设公司
  • 沈阳网站建设-中国互联商城页面
  • 成交型网站倡导公司进贤南昌网站建设公司
  • 网站跟软件有什么区别是什么点击器原理
  • 网站建设项目策划书范文杭州 网站开发公司
  • 酒店网站建设设计企业营销型网站策划
  • 用dw怎么做登录页面的网站成都微信网站建设推
  • 合肥网站建设案例美丽说网站模板
  • 大学网站建设管理办法手机网站如何推广
  • 本网站正在建设升级中常用的软件开发平台
  • 招标网站开发文档上海免费网站建站模板
  • 备案系统网站wordpress 条件查询