zoukankan      html  css  js  c++  java
  • 多态中的虚函数

    • 向上类型转换
     1 enum note {middleC,Csharp,Cflat};
     2 class Instrument {
     3 public:
     4     void  play(note) const {
     5         cout << "Instrument::play" << endl;
     6     }
     7 };
     8 
     9 class Wind: public Instrument {
    10 public:
    11     void  play(note) const {
    12         cout << "Wind::play" << endl;
    13     }
    14 };
    15 
    16 void ture(Instrument& i) {
    17 
    18     i.play(middleC);
    19 }
    20 int main()
    21 {
    22     Wind flute;
    23     tune(flute);
    24 //最终打印结果为Instrument::play,向上类型转换虽然对象属于Wind,
    25 //但是Wind继承于Instrument,这样ture(Instrument& i)即使传入的是Wind类,也能向上转换为Instrument类的对象
    26 
    27 }

    变为虚函数后的结果就不同了

     1 enum note {middleC,Csharp,Cflat};
     2 class Instrument {
     3 public:
     4     void  play(note) const {
     5         cout << "Instrument::play" << endl;
     6     }
     7 };
     8 
     9 class Wind: public Instrument {
    10 public:
    11     virtual void  play(note) const {
    12         cout << "Wind::play" << endl;
    13     }
    14 };
    15 
    16 void ture(Instrument& i) {
    17 
    18     i.play(middleC);
    19 }
    20 int main()
    21 {
    22     Wind flute;
    23     tune(flute);//最终打印结果为Wind::play ,加上virtual关键字后,就可以保证继承的可扩展性,保证派生类自已拥有不同于基类的功能,实现函数的重新定义。
    24 }
    • 抽象基类和纯虚函数

      在类的设计中,通常将基类作为派生类的一个标准接口,一般不创建基类的对象,建立基础的模板,它的派生类去重新定义函数的功能。纯虚函数禁止对抽象类的函数以传值方式调用,会发生对象切片,通过引用或指针可以避免。

     1 enum note {middleC,Csharp,Cflat};
     2 class Instrument {
     3 public:
     4     virtual void  play(note) const = 0;
     5     virtual char*  what() const = 0;
     6     virtual void  adjust(int) = 0;
     7 };
     8 
     9 class Wind: public Instrument {
    10 public:
    11     void  play(note) const
    12     {
    13         cout << "Wind::play" << endl;
    14     }
    15     char*  what() const
    16     {
    17         return "Wind";
    18 
    19     }
    20     void  adjust(int) {}
    21 };
    22 class Percussion : public Instrument {
    23 public:
    24     void  play(note) const
    25     {
    26         cout << "Percussion::play" << endl;
    27     }
    28     char*  what() const
    29     {
    30         return "Percussion";
    31 
    32     }
    33     void  adjust(int) {}
    34 };
    35 class Stringed : public Instrument {
    36 public:
    37     void  play(note) const
    38     {
    39         cout << "Stringed ::play" << endl;
    40     }
    41     char*  what() const
    42     {
    43         return "Stringed";
    44 
    45     }
    46     void  adjust(int) {}
    47 };
    48 class Brass : public Wind {
    49 public:
    50     void  play(note) const
    51     {
    52         cout << "Brass ::play" << endl;
    53     }
    54     char*  what() const
    55     {
    56         return "Brass";
    57 
    58     }
    59 };
    60 class Woodwind : public Wind {
    61 public:
    62     void  play(note) const
    63     {
    64         cout << "Woodwind ::play" << endl;
    65     }
    66     char*  what() const
    67     {
    68         return "Woodwind";
    69 
    70     }
    71 };
    72 void ture(Instrument& i) {
    73 
    74     i.play(middleC);
    75 }
    76 void f(Instrument& i)
    77 {
    78     i.adjust(1);
    79 }
    80 int main()
    81 {
    82     Wind flute;
    83     Percussion drum;
    84     Stringed violin;
    85     Brass fluge;
    86     Woodwind recorder;
    87     tune(flute);
    88     tune(drum);
    89     tune(violin);
    90     tune(fluge);
    91     tune(recorder);
    92     f(fluge);
    93 }
    • 对象切片

      解决多态中,基类对象操作派生类对象的问题,对象切片会使基类访问不到派生类,不能使多态有意义。

     1 class Pet {
     2     string pname;
     3 public:
     4     Pet(const string& name) :pname(name) {}
     5     virtual string name() const { return pname; }
     6     virtual string description()const
     7     {
     8         return pname;
     9     }
    10 };
    11 
    12 class Dog : public Pet {
    13     string factive;
    14 public:
    15     Dog(const string& name, const string& active) :Pet(name), factive(active) {}
    16     string description() {
    17         return factive;
    18     }
    19 };
    20 void  description(Pet p) //传入的使值,不是引用不是指针地址
    21 {
    22     cout << p.description() << endl;
    23 }
    24 
    25 int main()
    26 {
    27     Pet p("Alfred");
    28     Dog d("Fluffy","sleep");
    29     description(p);
    30     description(d);
    31 //我们希望description(p)出现Alfred结果,description(d)出现sleep结果,
    32 //但是实际最终的结果是description(d)出现Fluffy,调用的同样是基类的函数,
    33 //而不是派生类的。因为传值的过程不能改变地址。
    34 }
    • 重载和重新定义

      重新定义一个基类的重载函数时,将会隐藏所有该重载函数的其他基类函数,但是当对虚函数进行操作重新定义时会不太一样。下面的d4和引用是其中的区别.

     1 class Base {
     2 public:
     3     virtual int f()const {
     4         cout << "Base::f()";
     5         return 1;
     6     }
     7     virtual void f(string) const {}
     8     virtual void g() const {}
     9 };
    10 
    11 class Derived1 :public Base {
    12 public:
    13     void g() cont {}
    14 };
    15 class Derived2 :public Base {
    16 public:
    17     int f() cont {
    18         cout << "Derived2::f()";
    19         return 2;
    20     }
    21 };
    22 class Derived3 :public Base {
    23 public:
    24     /*void f() const {
    25         cout << "Derived3::f()";
    26         return 3;
    27     }*///非法,不能改变返回类型
    28 };
    29 class Derived4 :public Base {
    30 public:
    31     int f(int) cont {
    32         cout << "Derived4::f()";
    33         return 3;
    34     }
    35 };
    36 int main()
    37 {
    38     srting s("hello");
    39     Derived1 d1;
    40     int x = d1.f();
    41     d1.f(s);
    42     Derived2 d2;
    43     x = d2.f();
    44     //d2.f(s);隐藏
    45     Derived4 d4;
    46     x = d4.f(1);
    47     //x=d4.f();隐藏
    48     //d4.f(s);隐藏
    49     Base& br = d4;
    50     //br.f(1);
    51     br.f();
    52     br.f(s);//与Derived4 d4相反
    53 }
  • 相关阅读:
    Spring基础知识
    Hibernate基础知识
    Struts2基础知识
    在eclipse里头用checkstyle检查项目出现 File contains tab characters (this is the first instance)原因
    java后台获取cookie里面值得方法
    ckplayer 中的style.swf 中的 style.xml 中的修改方法
    java hql case when 的用法
    Windows下Mongodb安装及配置
    Mongodb中经常出现的错误(汇总)child process failed, exited with error number
    Mac 安装mongodb
  • 原文地址:https://www.cnblogs.com/fuzhuoxin/p/12153971.html
Copyright © 2011-2022 走看看