c++_4: 多态_1_虚函数的定义

多态的概念

  • 虚函数增强了类型的概念,而不是只是在结构内部隐藏代码;

向上类型转换

函数调用的bangding

  • 函数体和函数调用相联系称为捆绑
  • 早捆绑
  • 晚捆绑:运行时发生的捆绑-动态捆绑
  • virtual函数
  • 派生类的函数—–重写
//向上类型转换

#include <iostream>
using namespace std;
enum note { middleC,Csharp,Eflat };    //Etc.

class Instrument
{
public:
       void play(note) const
       {
                  cout<<"Instrument::play"<<endl;
       }
};

class Wind:public Instrument
{
public:
      void play(note) const
        {
                 cout<<"Wind::play"<<endl;
         }
};

void tune(Instrument& i)
{
           i.play(middleC);
}

int main()
{
          Wind flute;
          tune(flute);  //调用Instrument::paly//向上类型转换
}
  • 添加虚函数
//向上类型转换

#include <iostream>
using namespace std;
enum note { middleC,Csharp,Eflat };    //Etc.

class Instrument
{
public:
      virtaul  void play(note) const   // 虚函数
       {
                  cout<<"Instrument::play"<<endl;
       }
};


class Wind:public Instrument
{
public:
        //Redefine interface function:
        void play(note) const
        {
                 cout<<"Wind::play"<<endl;
         }
};

void tune(Instrument& i)
{
           i.play(middleC);
}

int main()
{
          Wind flute;
          tune(flute);  //调用Instrument::paly//向上类型转换
}
  • 声明为虚函数后,调用Wind::play

虚函数

  • 虚函数后,可以通过从公共基类继承新数据类型而增加新的功能
#include <iostream>
using namespace std;
enum note { middleC, Csharp, Cflat }; // Etc.

class Instrument {
public:
  virtual void play(note) const {
    cout << "Instrument::play" << endl;
  }
  virtual char* what() const {
    return "Instrument";
  }
  // Assume this will modify the object:
  virtual void adjust(int) {}
};

class Wind : public Instrument {
public:
  void play(note) const {
    cout << "Wind::play" << endl;
  }
  char* what() const { return "Wind"; }
  void adjust(int) {}
};

class Percussion : public Instrument {
public:
  void play(note) const {
    cout << "Percussion::play" << endl;
  }
  char* what() const { return "Percussion"; }
  void adjust(int) {}
};

class Stringed : public Instrument {
public:
  void play(note) const {
    cout << "Stringed::play" << endl;
  }
  char* what() const { return "Stringed"; }
  void adjust(int) {}
};

class Brass : public Wind {
public:
  void play(note) const {
    cout << "Brass::play" << endl;
  }
  char* what() const { return "Brass"; }
};

class Woodwind : public Wind {
public:
  void play(note) const {
    cout << "Woodwind::play" << endl;
  }
  char* what() const { return "Woodwind"; }
};

// Identical function from before:
void tune(Instrument& i) {
  // ...
  i.play(middleC);
}

// New function:
void f(Instrument& i) { i.adjust(1); }

// Upcasting during array initialization:
Instrument* A[] = {
  new Wind,
  new Percussion,
  new Stringed,
  new Brass,
};

int main() {
  Wind flute;
  Percussion drum;
  Stringed violin;
  Brass flugelhorn;
  Woodwind recorder;
  tune(flute);
  tune(drum);
  tune(violin);
  tune(flugelhorn);
  tune(recorder);
  f(flugelhorn);
} ///:~
  • 子类指针,指向派生类,通过调用派生类方法

虚函数的工作机制

http://blog.csdn.net/wanghaobo920/article/details/7674631

  • 为了达到晚绑定,编译器为每个包含虚函数的类创建一个虚函数表(VTABLE)
  • vpointer(VPTR)虚函数指针,多态时候,由基函数调用
  • 过程:为类设置VTABLE->初始化VPTR(虚函数指针)->为虚函数插入调用代码
class  NoVirtual
{
   int a;
   public:
     void x() const{}
     int i() const {return 1;}
};
class  OneVirtual
{
   int a;
   public:
     virtual void x() const{}
     int i() const {return 1;}
};
class  TwoVirtual
{
   int a;
   public:
     virtual void x() const{}
     virtual int i() const {return 1;}
};
  • sizeof(NoVirtual)=sizeof(int)
  • sizeof(onevirtual)=sizeof(novirtual)+sizoef(void)=在架构中插入一个单指针(VRTP)
  • sizeof(twovirtual)=sizeof(onevirtual)

虚函数的功能

  • 虚函数表(参看c++编程思想p361)

c++_4: 多态_1_虚函数的定义_第1张图片

  • 在类中插入VPTR(vpointer)
  • vpointer指向虚函数表(编译器为每个类创建虚函数表)
  • 虚函数表中存放:子类的虚函数或者是派生类的函数地址
  • 若派生类没有重新定义子类的虚函数,则存放基类的虚函数地址:Brass object
  • VPTR被初始化为虚函数表VTABLE的地址

这里写图片描述

  • 基类调用虚函数地址
class Mammal
{
    public:
       virtual speak();
       move();
};
Class Dog : public Mammal
{
    void speak();
    void move();
};

int main()
{
    Mammal *pDog=new Dog;
    pDog->Move(); // 调用Mammal的方法---Mammal::move
    pDog->speak();  //调用Dog的方法---Dog::speak---虚函数
}
  • vpoiter通常在对象的开头
  • 取出vpointer
  • vpointer指向vtable的起始位置
  • 晚绑定

你可能感兴趣的:(c++_4: 多态_1_虚函数的定义)