运行期多态(虚函数)和编译器多态(模板)
运行期多态的说明示例:
class Animal //基类
{
public :
virtual void shout() = 0;
};
class Dog :public Animal
{
public:
virtual void shout(){ cout << "汪汪!"<<endl; }
};
class Cat :public Animal
{
public:
virtual void shout(){ cout << "喵喵~"<<endl; }
};
void main()
{
Animal * anim1 = new Dog;
Animal * anim2 = new Cat;
//藉由指针(或引用)调用的接口,在运行期确定指针(或引用)所指对象的真正类型,调用该类型对应的接口--运行期多态
anim1->shout();
anim2->shout();
//delete 对象
...
}
编译期多态的说明示例:
class Animal
{
public :
void shout() { cout << "发出动物的叫声" << endl; };
};
class Dog
{
public:
void shout(){ cout << "汪汪!"<<endl; }
};
class Cat
{
public:
void shout(){ cout << "喵喵~"<<endl; }
};
template <typename T>
void animalShout(T & t)
{
t.shout();//在编译期间,编译器推断出模板参数,因此确定调用的shout是哪个具体类型的接口。--编译期多态
}
int main()
{
Animal anim;
Dog dog;
Cat cat;
animalShout(anim);
animalShout(dog);
animalShout(cat);
}
显式接口(class)和隐式接口(template)
组成 | 什么时候完成检查 |
---|---|
显式接口 | 函数的签名式(函数名称,参数类型、返回类型) |
隐式接口 | 有效表达式 |
显式接口的说明示例:
class widget{
public:
widget();
virtual ~widget();
virtual std::size_t size() const;
void swap(widget& other);
};
//其public接口由一个构造函数、一个析构函数、size函数、swap函数及其参数类型、返回类型、常量性构成。也包括编译器产生的copy函数(copy构造函数和copy assignment操作符)
隐式接口的说明示例:
template<typename T>
void dofun(T& w)
{
if(w.size() > 10 && w != value){...}
}
//T必须支持size成员函数,然而这个函数也可能从base class继承。这个成员函数不需返回一个整数值,甚至不需返回一个数值类型。就此而言,甚至不需要返回一个定义有operator>的类型!唯一需要的是返回一个类型为X的对象,X对象加上int必须能调用一个operator>。
//同样的道理,T并不需要支持operator!=,因为operator!=接受一个类型为X的对象和一个类型为Y的对象,T可被转换为X而value的类型可被转换为Y,这样就可以有效调用operator!=