码迷,mamicode.com
首页 > 其他好文 > 详细

多态与继承

时间:2015-10-28 17:19:04      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:


1.多态
    多态是通过虚函数来实现的,也就是说虚函数是允许子类重新定义成员函数,而子类通过定义和父类一样的函数的方法,被成为覆盖或者是重写。
    多态的作用,使得代码可以重用,代码模块化;

函数重写:
    (1)子类定义的函数与父类原型相同的函数
    (2)函数的重写只有发生在父类和子类之间
  1. class Parent
  2. {
  3. public:
  4. void f()
  5. {
  6. cout << "Parent" << endl;
  7. }
  8. };
  9. class Child : public Parent
  10. {
  11. public:
  12. void f()
  13. {
  14. cout << "Child" << endl;
  15. }
  16. };
  17. int main()
  18. {
  19. Child c1;
  20. c1.f();
  21. while (1);
  22. }
    打印出子类的同名函数:Child,除非使用 c1.Parent::f(); 才会执行 父类的打印函数,一般的情况是,编译器会将父类的打印函数进行隐藏,使用的是子函数重写的函数去执行,

  1. void run()
  2. {
  3. Child c1;
  4. c1.f();
  5. Parent *pp = &c1;
  6. pp->f(); // 父类的打印
  7. Parent &ppp = c1;
  8. ppp.f(); // 父类的打印
  9. }
  10. int main()
  11. {
  12. run();
  13. while (1);
  14. }
打印出来:
  1. Child
  2. Parent
  3. Parent
    打印结果,居然和分析不一样,原因是:C和C++是静态编译型语言(编译器会根据指针的类型去判断执行的是一个什么用的对象),所以,我们的指针和引用的是 是 Parent,所以执行的时候,输出的结果是父类的打印函数。言而总之,总而言之,我们就看指针,指针是什么类型。

多态的本质:
    通过添加 virtual 关键字对多态进行支持,将会被子类进行重写的函数,前面加上 virtual 关键字,
  1. class Parent
  2. {
  3. public:
  4. virtual void f()
  5. {
  6. cout << "Parent" << endl;
  7. }
  8. };
  9. class Child : public Parent
  10. {
  11. public:
  12. void f()
  13. {
  14. cout << "Child" << endl;
  15. }
  16. };
  17. void run()
  18. {
  19. Child c1;
  20. c1.f();
  21. Parent *pp = &c1;
  22. pp->f();
  23. Parent &ppp = c1;
  24. ppp.f();
  25. }
  26. 这三个打印输出的就是: child child child
    只要在会被进行函数重写的函数假如 virtual 关键字,那么这个函数就是虚函数,到具体使用的时候,就会根据实际的情况进行打印输出。传入的是什么类型的,打印的就是什么类型的。

重载和重写的区别:什么时候重载、什么时候重写
    (1)重载:
        A 是同时存在多个同名的函数,但是在参数的个数,参数的类型、参数的顺序存在区别,
        B 事实上,重载只能发生在一个类里面,继承是不能实现函数的重载。
        C 原理上,C++编译器根据参数的不同,重新生成函数名,所以不同的参数会生成不同的函数名,所以本质上就是不同的函数了,也就是说编译器在编译的时候,就已经可以区分到底调用的是哪一个重载的函数,编译器早早已经确定,这些函数的编译的时候的地址就已经是被绑定了(早绑定)。
    (2)重写:
        A 是指子类重新定义父类的虚函数。子类重新定义了父类的虚函数,
        B 必须是发生在父类和子类之间。 父类和子类中的函数,必须完全相同的原型
        C 使用 virtual 可以产生多态
        D 多态是在运行的期间跟根据具体的对象的类型决定调用函数。

将所有的函数都加上 virtual 关键字:
    完全没有必要,这就涉及到虚函数的实现编译器将包含了 virtual 的虚函数的函数信息,存放到虚函数表里面,每次运行的时候,都会去虚函数表里面进行比对,看看是不是虚函数,如果是的话,那么就使用虚函数表里面的函数,不是的话,就去运行类内部其他的函数,所以不要将所有的函数全部设置为虚函数,会造成大量的浪费,处于效率考虑的话,其实就不要全部设置为虚函数。


纯虚函数:
    是一种特殊的虚函数,在基类中(父类)不能对虚函数给据有意义的实现,而把他声明为纯虚函数,它的实现则留给子类去做,这就是纯虚函数的作用,
    纯虚函数在父类只做函数原型的声明,而故意不定义函数体的虚函数,函数的定义等子类去完成(必须),这样就完成了纯虚函数的作用。
  1. class Shape
  2. {
  3. public: // 纯虚函数声明,没有实际的意义
  4. virtual double area() = 0;
  5. };
  6. class Rectangle : public Shape
  7. {
  8. double a;
  9. double b;
  10. public:
  11. Rectangle(double a, double b)
  12. {
  13. this->a = a;
  14. this->b = b;
  15. }
  16. // 函数的重写,纯虚函数重写
  17. double area()
  18. {
  19. return a * b;
  20. }
  21. };
  22. void area(Shape *s)
  23. {
  24. cout << s->area() << endl;
  25. }
  26. void run()
  27. {
  28. Rectangle rectangle(3, 4);
  29. cout<<"area is "<<rectangle.area()<<endl;
  30. area(&rectangle); // 可以使用指针
  31. //Shape shape; // 不能定义抽象类
  32. }
   看到纯虚函数的声明是,virtual 函数 = 0; 告诉编译器,这个只是声明,所以必须在子类去实现这个函数;注意到: 抽象类(shape,包含了一个纯虚函数的类)已经是不能定义对象了,但是仍然可以使用指针。

注意:
    不要将多态应用于数组当中,

多重继承:
    多重继承就是 子类既继承自父类1,同时也继承父类2。实际的应用中,是不使用多重继承,


















    
    



































































































多态与继承

标签:

原文地址:http://www.cnblogs.com/qxj511/p/4917700.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!