多态
多态的实现类型
联编的概念
静态联编和动态联编的区别
虚函数的声明主要内容
Instrument
play()
Wind
play()
Stringed
play()
Percussion
play()
由乐器类 Instrument派生出管乐器类 Wind、铉乐器类
Stringed、打击乐器类 Percussion。
请给出图中各类的定义,根据定义编写一个关于奏乐的程序。
Instrument类的定义:
class Instrument
{
};
public:
void play()
{ cout<<“instrument play”<<endl; }
Wind类的定义:
class Wind:public Instrument
{
};
public:
void play() //改写基类的 play()函数
{ cout<<“wind play”<<endl; }
Stringed类的定义:
class Stringed:public Instrument
{
};
public:
void play() //改写基类的 play()函数
{ cout<<“stringed play”<<endl; }
Percussion类的定义:
class Percussion:public Instrument
{
};
public:
void play() //改写基类的 play()函数
{ cout<<“percunssion play”<<endl; }
void tune(Wind i) //管乐器奏乐
{
} i.play();
……
void tune(Stringed i) //铉乐器奏乐
{
} i,play();
……
void tune(Percussion i) //打击乐器奏乐
{
} i,play();
……
void main()
{
}
Wind flute;
Stringed violin;
Percussion drum;
tune(flute);
tune(violin);
tune(drum);
如果增加乐器种类,则同样的代码要重复多次,
只有参数不同!
void tune(Wind i)
{
} i.play();
void tune(Stringed i)
{
} i,play();
void tune(Percussion i)
{
} i.play();
……
……
……
改进 1:
void tune(Instrument& i) //向上转型
{
} i.play();
……
void main()
{
}
Wind flute;
Stringed violin;
Percussion drum;
tune(drum);
tune (flute);
tune (violin);
class Wind
{
};
……
void play()
{ cout<<“Wind play”<<endl; }希望
class Instrument
{
};
……
void play()
{ cout<<“instrument play”<<endl; }
实际改进 2,(在向上转型基础上 )
void tune(Instrument& i) //向上转型
{
} i.play();
……
{
};
public:
virtual void play() //虚函数
{ cout<<“instrument play”<<endl; }
class Instrument
class Wind:public Instrument
{
};
public:
vitual void play() //virtual可省略
{ cout<<“wind play”<<endl; }
class Percussion:public Instrument
{
};
public:
virtual void play //virtual可省略
{ cout<<“percunssion play”<<endl; }
void main()
{
}
Wind flute;
Stringed violin;
Percussion drum;
tune(drum);
tune (flute);
tune (violin);
class Stringed:public Instrument
{
};
public:
vitual void play() //virtual可省略
{ cout<<“Stringed play”<<endl; }
实现机制
向上转型,基类指针 (引用 ) 派生类对象名
虚函数
flute
violin
drum
tune(i)
flute play
violin play
drum play
派生类对象 行为基类的引用
tune(Instrment& i)
tune(flute)
多态类中同一函数名对应多个具有相似功能的不同函数,
可以使用相同的调用方式来调用。
编译时多态:函数重载、运算符重载
void main()
{
}
int a[3];
char b[3];
float b[3];
max(a);
max(b);
max(c);
int max(int arr[]){……}
char max(char arr[]){……}
float max(float arr[]){……}
采用静态联编实现!
运行时多态 —采用动态联编
采用向上转型和虚函数
void main()
{
}
Wind flute;
Stringed violin;
Percussion drum;
tune(drum);
tune (flute);
tune (violin);
在面向过程程序设计中,所有程序都是采用静态联编来实现。静态联编的特点是函数调用速度快、
效率较高,但是编程灵活性不够。
动态联编虽然效率较静态联编低,但是能实现更灵活、更易维护、逻辑关系更清晰的代码。
静态联编 vs,动态联编虚函数
virtual <返回值类型 > <函数名 > <(参数表 )>;
虚函数只能是类中的非静态成员函数;
基类的成员函数一旦被声明为虚函数,每一层派生类中该函数都保持虚函数特性,在其派生类中其关键字
virtual可省略;
声明格式:
说明:
如果某类中的一个成员函数被说明为虚函数,这就意味着该成员函数在派生类中可能有不同的函数实现 ;
例 5-2 class Student{
public:
virtual void print()
{
}
cout<<“A student”<<endl;
};
class GStudent:public Student
{
public:
virtual void print()
{
}
cout<<“A graduate student”<<endl;
};
具有相似功能的函数采用相同函数名
void main()
{
Student s1,*ps;
GStudent s2;
ps = &s1;
};
ps = &s2;
ps->print();
ps->print();
class Student
{
public:
virtual void print()
{
}
cout<<“A student”<<endl;
};
class GStudent:public Student
{
public:
virtual void print()
{
}
cout<<“A graduate student”<<endl;
};
通过相同方式调用具有不同功能的同名函数。
ps->print();
s1
print()
s2
print()
A student
A graduate student
消息对象 行为注意:
派生类定义虚函数的时候,必须保证函数的返回值类型和参数与基类中的声明完全一致。
可将类中具有共性的成员函数声明为虚函数。
虚函数必须是类中的非静态成员。
内联函数不能声明为虚函数。
只能通过对象指针或引用来调用虚函数才能实现动态联编。