做机械设备哪个网站好,东莞网站推广哪里找,网站开发人员绩效考核,18款禁用黄a免费学习C的多态性#xff0c;你必然听过虚函数的概念#xff0c;你必然知道有关她的种种语法#xff0c;但你未必了解她为什么要那样做#xff0c;未必了解她种种行为背后的所思所想。深知你不想在流于表面语法上的蜻蜓点水似是而非#xff0c;今天我们就一起来揭开挡在你和虚… 学习C的多态性你必然听过虚函数的概念你必然知道有关她的种种语法但你未必了解她为什么要那样做未必了解她种种行为背后的所思所想。深知你不想在流于表面语法上的蜻蜓点水似是而非今天我们就一起来揭开挡在你和虚函数女神之间的这一层窗户纸。 首先我们要搞清楚女神的所作所为即语法规范。然后再去探究她背后的逻辑道理。她的语法说来也不复杂概括起来就这么几条 1.在类成员方法的声明不是定义语句前面加个单词virtual她就会摇身一变成为虚函数 2.在虚函数的声明语句末尾中加个 0 她就会摇身一变成为纯虚函数 3.子类可以重新定义基类的虚函数我们把这个行为称之为复写override 4.不管是虚函数还是纯虚函数基类都可以为他们提供实现implementation如果有的话子类可以调用基类的这些实现 5.子类可自主选择是否要提供一份属于自己的个性化虚函数实现 6.子类必须提供一份属于自己的个性化纯虚函数实现。 语法都列出来了背后的逻辑含义是什么呢我们用一个生动的例子来说明虚函数是如何实现多态性的。 假设我们要设计关于飞行器的类并且提供类似加油、飞行的实现代码考虑具体情况飞行器多种多样有民航客机、歼击机、轰炸机、直升机、热气球、火箭甚至窜天猴、孔明灯、纸飞机 假设我们有一位牛得一比的飞行员他能给各式各样的飞行器加充不同的燃料也能驾驶各式各样的飞行器。下面我们来看看这些类可以怎么设计。 首先飞行器。由于我们假设所有的飞行器都有两种行为加油和飞行。因此我们可以将这两种行为抽象到一个基类中并由它来派生具体的某款飞行器。 1 // 这是一个描述飞行器的基类提供了两个基本的功能加油和飞行。
2 class aircraft {
3 virtual void refuel(); // 加燃油普通虚函数
4 virtual void fly()0; // 飞行纯虚函数
5 }; 1 // 这是一个普通虚函数意味着基类希望子类提供自己的个性化实现代码但基类
2 // 同时也提供一个缺省的虚函数实现版本在子类不复写该虚函数的情况下作为备选方案。
3 void aircraft::refuel() {
4 // 加通用型燃油
5 std::cout 加通用燃油 std::endl;
6 } 1 // 这是一个纯虚函数意味着基类强制子类必须提供自己的个性化版本否则编译将失败。
2 void aircraft::fly() {
3 // 一种不应该被使用的缺省飞行方案
4 std::cout 一种不应该被使用的缺省飞行方案 std::endl;
5 } 但让人惊奇的是C仍然保留了基类提供该纯虚函数代码实现的权利这也许是给千变万化的实际情况留下后路。 有了基类aircraft我们就可以潇洒地派生出各式各样的飞行器了比如轰炸机和直升机 1 // 轰炸机类定义复写了加油和飞行2 class bomber : public aircraft {3 void refuel() {} // 加轰炸机的特殊燃油4 void fly() {} // 轰炸机实弹飞行5 };6 7 // 直升机类定义复写了飞行代码但没有复写加油8 class copter : public aircraft {9 void fly() {} // 直升机盘旋
10 }; 以上代码可以看到直升机类copter没有自己的加油方式直接使用了基类提供的缺省加油的方式。此时我们来定义一个能驾驭多机型的王牌飞行员类 1 // 一个能驾驶各种飞行器的王牌飞行员
2 class pilot {
3 void refuelPlane(aircraft *p);
4 void dirvePlane(aircraft *p);
5 }; 1 // 给我什么飞机我就加什么油
2 void pilot::refuelPlane(aircraft *p) {
3 p-refuel();
4 }
5
6 // 给我什么飞机我就怎么飞
7 void pilot::dirvePlane(aircraft *p) {
8 p-fly();
9 } 很明显我们接下来要给这位很浪的飞行员表演一下操纵各种飞行器的机会我们来定义各种飞机然后丢给他去处理。 1 // 定义两架飞机一架轰6K一架武直10
2 aircraft *H6K new bomber;
3 aircraft *WZ10 new copter; 1 // 来一个王牌飞行员给H6K加油加的是轰炸机特殊燃油并且按照H6K的特点飞行
2 pilot Jack;
3 Jack.refuelPlane(H6K); // 加轰炸机燃油
4 Jack.flyPlane(H6K); // 轰炸机实弹飞行
5
6 // 给WZ10加油加的是基类提供的通用燃油按照WZ10的特点飞行
7 Jack.refuelPlane(WZ10); // 加通用型燃油
8 Jack.flyPlane(WZ10); // 直升机盘旋 上述代码体现了最经典的所谓多态的场景给Jack不同的飞机就能表现不同的结果。虚函数和纯虚函数都能做到这一点区别是子类如果不提供虚函数的实现那就会自动调用基类的缺省方案。而子类如果不提供纯虚函数的实现则编译将会失败。基类提供的纯虚函数实现版本无法通过指向子类对象的基类类型指针或引用来调用因此不能作为子类相应虚函数的备选方案。 下面给出总结 1.当基类的某个成员方法在大多数情形下都应该由子类提供个性化实现但基类也可以提供一个备选方案的时候请将其设计为虚函数。例如飞行器的加油动作每种不同的飞行器原则上都应该有自己的个性化的加充燃油的方式但也不免可以有一种通用的燃油加充方式 2.当基类的某个成员方法必须由子类提供个性化实现的时候请将其设计为纯虚函数。例如飞行器的飞行动作逻辑上每种飞行器都必须提供为其特殊设计的个性化飞行行为而不应该有任何一种通用的飞行方式 3.使用一个基类类型的指针或者引用来指向子类对象进而调用经由子类复写了的个性化的虚函数这是C实现多态性的一个最经典的场景 4.基类提供的纯虚函数的实现版本并非为了多态性考虑因为指向子类对象的基类指针和引用无法调用该版本。纯虚函数在基类中的实现跟多态性无关它只是提供了一种语法上的便利在变化多端的应用场景中留有后路 5.虚函数和普通的函数实际上是存储在不同的区域的虚函数所在的区域是可被覆盖也称复写override的每当子类定义相同名称的虚函数时就将原来基类的版本给覆盖了另一侧面也说明了为什么基类中声明的虚函数在后代类中不需要另加声明一律自动为虚函数因为它所存储的位置不会发生改变。而普通函数的存储区域不会覆盖每个类都有自己独立的区域互不相干。 转自https://blog.csdn.net/vincent040/article/details/78848322并对代码做了小幅修正在此感谢原作者。 转载于:https://www.cnblogs.com/chwei2ch/p/10628608.html