多 态
1、动态多态的实现原理
2、多态的类别及实现方法
3、动态多态的四种情况
(2)多态的类别及实现方法
2.1 静态多态:编译时多态、函数的多态性,重载、模板、宏
2.2 动态多态:运行时多态、类的多态性,继承和虚函数,晚绑定、动态绑定
2.3 封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是哪个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。
(3)动态多态的四种情况
3.1 用一个父类的指针指向一个子类对象
3.2 用一个父类的指针当函数的形参,用这个指针可以接受到任何它的子类对象也包括他自己
3.3 在复合类,尽量饮用高层次的类(父类的指针)当做类的成员变量,这样就可以通过它创建出它所对应的任何子类对象包括他自己
3.4 在容器中,可以声明一个父类指针的容器,这时可以往容器中添加它所对应的任何子类对象包括他自己
//这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
//(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
//(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
//上面的程序中:
//(1)函数Derived::f1(float)覆盖了Base::f1(float)。
//(2)函数Derived::f2(int)隐藏了Base::f2(float),而不是重载。
//(3)函数Derived::f3(float)隐藏了Base::f3(float),而不是覆盖
#ifndef __C__No807Class__Father__
#define __C__No807Class__Father__
#include <iostream>
using namespace std;
class Father
{
public:
virtual void print();
};
#endif /* defined(__C__No807Class__Father__) */
#include "Father.h"
void Father::print()
{
cout << "Father print" << endl;
}
#ifndef __C__No807Class__Son__
#define __C__No807Class__Son__
#include <iostream>
#include "Father.h"
class Son : public Father
{
public:
void print();
};
#endif /* defined(__C__No807Class__Son__) */
#include "Son.h"
void Son::print()
{
cout << "Son print" << endl;
}
#ifndef __C__No807Class__Son2__
#define __C__No807Class__Son2__
#include <iostream>
#include "Father.h"
class Son2 : public Father
{
public:
void print();
};
#endif /* defined(__C__No807Class__Son2__) */
#include "Son2.h"
void Son2::print()
{
cout << "Son2 print" << endl;
}
#include <iostream>
#include<string>
#include<vector>
#include "Son.h"
#include "Son2.h"
//如果容器中函数的对象是不同类的,那么这时候用使用多态是非常的方便的
void func(const vector<Father*>&V) //容器中,可以声明一个父类指针的容器,可以往这个容器中添加它所对应的任何子类对象包括他自己
{
for(int i = 0; i < V.size(); ++i)
{
V.at(i) -> print();
}
}
void foo(Father &f) //父类指针当函数形参,用这个指针可以接受到任何它的子类对象也包括他自己
{
f.print(); //Son,不加引用Father
}
int main()
{
Son s;
Son2 s2;
Father f;
Father *p;
p = &s; //父类指针指向子类对象
p -> print();
p = &s2;
p -> print();
foo(s);
vector<Father*>FatherVector;
FatherVector.push_back(&s);
FatherVector.push_back(&s2);
FatherVector.push_back(&f);
func(FatherVector);
return 0;
}
B、静态多态--重载
#include <iostream>
#include <string>
using namespace std;
int add (int num1, int num2)
{
return (num1 + num2);
}
int add (int num1, string str1)
{
return (num1 + atoi(str1.c_str())); //把字符串的数字转为数字型的数值
}
int add (int num1, char c1)
{
return (num1 + c1);
}
int main()
{
int n1 = 10, n2 = 20;
string s1 = "30";
char c1 = 'a';
cout << n1 << " + " << n2 << " = " << add(n1, n2) <<endl;
cout << n1 << " + " << s1 << " = " << add(n1, s1) <<endl;
cout << n1 << " + " << c1 << " = " << add(n1, c1) <<endl;
return 0;
}
C、静态多态--模板
template <typename T>
T max(const T& i, const T& j)
{
return (i > j) ? i : j;
}
//返回两个任意类型对象的最大值(对象),前提是该类型能够使用>运算符进行比较,并且返回值是bool类型。
使用:
int a = 3; int b = 4;
cout << max(a, b) << endl;
float c = 2.4; float d = 1.2;
cout << max(c, d) << endl;
输出结果为:
4
2.4
这种绑定发生在编译期,这是由于模板的实例化是发生在编译期的,即在编译时编译器发现你调用max(a, b)时就自动生成一个函数
int max(const int& i, const int& j)
{
return (i > j) ? i : j;
}
即将所有的T替换成int;
当你调用max(c, d)时就自动生成一个函数
float max(const float& i, const float& j)
{
return (i > j) ? i : j;
}
模板2
#include<iostream>
#include<string>
#include<vector>
using namespace std;
/*虚函数机制*/
class Base
{
public:
virtual void print()=0;
};
class Child1:public Base
{
void print()
{
cout<<"我是Child1类"<<endl;
}
};
class Child2:public Base
{
void print()
{
cout<<"我是Child2类"<<endl;
}
};
/*如果容器中函数的对象是不同类的,那么这时候用使用多态是非常的方便的*/
void func(const vector<Base*>&V)
{
for(int i=0;i<V.size();++i)
{
V.at(i)->print();
}
}
/*静态多态,使用模板*/
template<typename T>
void TempalteFuncion(const vector<T*>&V)
{
for(int i=0;i<V.size();++i)
{
V.at(i)->print();
}
}
int main()
{
/*虚函数多态 模板多态混用*/
Child1 child1;
Child2 child2;
Base *p;
p=&child1;
p->print();
p=&child2;
p->print();
vector<Base*>BaseVector;
BaseVector.push_back(&child1);
BaseVector.push_back(&child2);
func(BaseVector);
TempalteFuncion(BaseVector);
return 0;
}
D、静态多态--宏多态(忽略)
#include<iostream>
#include<string>
using namespace std;
#define ADD(A,B) ((A)+(B))
void main()
{
/*宏多态*/
int num1=10;
int num2=20;
string str1="22";
string str2="33";
cout<<"宏多态 ADD(A+B) A+B:"<<ADD(num1,num2)<<endl;
cout<<"宏多态 ADD(A+B) A+B:"<<ADD(str1,str2)<<endl;
}
E、子类指针指向父类对象、隐藏
#include <iostream>
using namespace std;
class A
{
public:
void f1()
{
cout << "1" << endl;
}
virtual void f2()
{
cout << "2" << endl;
}
};
class B : public A
{
public:
void f1()
{
cout << "3" << endl;
}
void f2()
{
cout << "4" << endl;
}
};
int main()
{
A a;
B b;
A *p = &a;
p -> f1(); //1
p -> f2(); //2
p = &b;
p -> f1(); //1
p -> f2(); //4
B *ptr = (B *)&a; //子类指针ptr,父类对象a的引用强制转化为B类类型指针
ptr -> f1(); //3
ptr -> f2(); //2
return 0;
}
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f1(float x)
{
cout << "Base f1 (float) = " << x << endl;
}
void f2(float x)
{
cout << "Base f2 (float) = " << x << endl;
}
void f3(float x)
{
cout << "Base f3 (float) = " << x << endl;
}
};
class Derived : public Base
{
public:
void f1(float x)
{
cout << "Derived f1 (float) = " << x << endl; //覆盖,多态
}
void f2(int x)
{
cout << "Derived f2 (float) = " << x << endl; //隐藏
}
void f3(float x)
{
cout << "Derived f3 (float) = " << x << endl; //隐藏
}
};
int main()
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
pb -> f1(3.14f); //D f1
pd -> f1(3.14f); //D f1
pb -> f2(3.14f); //B f2
pd -> f2(3.14f); //D f2
pb -> f3(3.14f); //B f3
pd -> f3(3.14f); //D f3
return 0;
}
//这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
//(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual 关键字,基类的函数将被隐藏(注意别与重载混淆)。
//(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
//上面的程序中:
//(1)函数Derived::f1(float)覆盖了Base::f1(float)。
//(2)函数Derived::f2(int)隐藏了Base::f2(float),而不是重载。
//(3)函数Derived::f3(float)隐藏了Base::f3(float),而不是覆盖