huangfu Blog
Love Leanote!
Toggle navigation
huangfu Blog
主页
About Me
归档
标签
11多继承/虚继承/虚函数/函数重写(覆盖)
2017-02-19 17:03:20
79
0
0
tarena
#多继承 ##概念 一个类可以有多个直接父类 ##语法 > class Iphone:public Phone,public Camera,public Mp3 { } 父类`构造函数的调用顺序和继承顺序一致`,与其他无关 ##多继承引入的冲突问题 假如继承的3个父类都有一个函数叫getPrice(),子类在调用该函数时,会产生歧异,不知调用哪个getPrice(). 该问题的解决方案有多个 * 利用名字隐藏机制解决 * 利用虚继承解决 1. 抽取共有部分到更高层的一个类中 2. 采用虚继承 继承更高层的类 ##举例 #include <iostrea> using namespace std; class Phone { double price; Phone(double Price = 2000) :price(price) { cout << "Phone()" << endl; } double getPrice() { return price; } void call(string pno) { cout << "给号码" << pno << "打电话" << endl; } }; class Camera { double price; public: Camera(double price = 3500) :price(price) { cout << "Camera()" << endl; } double getPrice() { retunr price; } void camera() { cout << "拍视频" << endl; } }; class Mp3 { double price; public: Mp3(double price = 88) :price(price) { cout << "Mp3()" << endl; } double getPrice() { return price; } void play(string music) { cout << "播放音乐 " << music << endl; } }; /* 构造函数的调用顺序只和这里继承顺序有关,和其他无关*/ class Iphone:public Phone,public Camera,public Mp3 { public: /* 构造函数的调用顺序和这里初始化表顺序无关*/ Iphone(double p, double c, double m):Phone(p), Mp3(m), Camera(c) { } /* 这里提供了getPrice函数,继承下来的其他getPrice函数被隐藏掉*/ double getPrice() { return Phone::getPrice() + Camera::getPrice() + Mp3::getPrice(); } }; int main() { Iphone iphone; /* 证明成员函数确实被继承了*/ iphone.call("15641151701"); iphone.camera(); iphone.play("传奇"); /* 证明成员变量也被继承了*/ cout << sizeof iphone << endl; /* 如果子类中没有getPrice函数且调用了继承下来的getPrice函数,程序会产生歧异,编译不通过*/ // cout << iphone.getPrice() << endl; /* 使用名字隐藏机制,解决调用冲突*/ cout << iphone.Phone::getPrice() << endl; // 2000 /* 当子类中提供了getPrice()函数,继承下来的其他getPrice函数被隐藏掉,条用不会再产生歧异*/ cout << iphone.getPrice() << endl; // 5588 } #虚继承 virtual #include <iostream> using namespace std; /* 抽取共有部分*/ class Product { double price; public: Prodect(double price = 0.0) :price(price) { } double getPrice() { return price; } }; class Phone:virtual public Product { public: Phone(double price):Product(price) { } void call(string pno) { cout << "给号码" << pno << "打电话" << endl; } }; class Camera:virtual public Product { public: Camera(double price):Product(price) { } void camera() { cout << "拍视频" << endl; } } class Mp3:virtual public Product { public: Mp3(double price):Product(price) { } void play(string music) { cout << "播放音乐 " << music << endl; } }; /* 则里需然省略了虚继承,但它们默认是虚继承,一虚全虚*/ class Iphone:public Phone,public Camera,public Mp3 { public: /* 这里先会调用Product的构造函数*/ Iphone(double p = 2000,double c = 3500, double m = 88):Product(p+c+m),Phone(p),Camera(c),Mp3(m) { } }; int main() { /* 创建该对象,会先调用Product的构造函数,再依次按照继承顺序,调用父类的构造函数 但是在调用父类构造函数时,不会继续向上构造,也就是调用完Phone构造函数后,不会再继续向上调用Product的构造函数*/ Iphone iphone(2000,3500,88); /* 虚继承的代价就是每多一个虚继承,会多一个指针来管理*/ cout << siezof(Phone) << endl; // 16 (double8 + 指针8) cout << siezof(Camera) << endl; // 16 cout << siezof(Mp3) << endl; // 16 cout << siezof(Iphone) << endl; // 32 (double8 + 3*指针8) /* 私有部分成功被继承*/ iphone.call("15641151701"); iphone.camera(); iphone.play("传奇"); cout << iphone.getPrice() << endl; // 5588 } #虚函数 ##概念 在普通成员函数前加了virtual修饰的函数 ##语法 > virtual void foo(); 当一个`类型中提供了虚函数,则编译器会自动增加一个指针类型的成员来管理虚数据`, 如果有多个虚函数,该指针也是一个,因为该指针`指向一个表格`,该指针叫`虚表指针` `继承来的虚表指针`和`虚函数产生的虚表指针`有些编译器是同一个,有写编译器是不同的. ###怎么能拿到虚表指针??? #函数重写 ##概念 当子类中提供了和父类同名且同返回值的`虚函数`时,称之为`函数重写` ##举例 #include <iostream> using namespace std; class Animal { public: void show() { cout << "animal show()" << endl; } virtual void run() { cout << "animal run()" << endl; } }; class Cat { public: /* 这叫名字隐藏,返回值可以不同*/ void show() { cout << "cat show()" << endl; } /* 这叫函数重写,返回值必须相同*/ /* 这里virtual关键字可以省略,默认就是虚函数,虚函数也遵循一虚全虚原则*/ valtual void run() { cout << "cat run" << endl; } }; int main() { /* 这就是多肽,一个行为有多种形态*/ Animal p = new Cat(); p->show(); // animal show p->run(); // cat run }
上一篇:
12多态/类型识别(dynamic_cast 和 typeid)
下一篇:
09string/迭代器iterator/面向对象编程三大特征/继承
0
赞
79 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册