首先多肽分为了两大类,一个是静态多态,一个是动态多态
什么是静态多态,静态多态就是我们曾经使用过的一个重载,什么叫做重载,比如两个函数的函数名相同,返回值相同,但是参数不同,我们可以称之为重载,重载分为两个大方面,运算符重载和函数重载运算符重载不会的童鞋欢迎看我之前的博客 这个就是静态多态这个很简单,随便举两个例子
第一个函数重载:
#include
using namespace std;
int add(int a,int b)
{
return a+b;
}
int add(int a,int b,int c)
{
return a+b+c;
}
int main()
{
int a,b,c;
cin>>a>>b>>c;
cout<<add(a,b)<<endl;
cout<<add(a,b,c)<<endl;
return 0;
}
这个就是最简单最基础的一个函数的重载,他们的函数名相同但是他们的参数个数不同
第二个运算符重载:
#include
using namespace std;
class node
{
protected:
int real,imag;
public:
node(){}
node(int r,int m){real=r,imag=m;}
friend node operator +(node &,node &);
friend ostream &operator <<(ostream &out,node &n);
};
node operator +(node &x,node &y)
{
node tmp;
tmp.real=x.real+y.real;
tmp.imag=x.imag+y.imag;
return tmp;
}
ostream &operator <<(ostream &out,node &n)
{
out<<n.imag<<" "<<n.real<<endl;
return out;
}
int main()
{
node node_1,node_2;
int r,m;
cin>>r>>m;
node_1=node(r,m);
cin>>r>>m;
node_2=node(r,m);
node ans;
ans=node_1+node_2;
cout<<ans<<endl;
return 0;
}
这个就是个非常简单的运算符重载的代码。
然后我们静态多态到这里就可以说是完事了,接下来要引出来的就是动态多态了
动态多态之前我们要明白
动态多态和静态多态的一个区别:
就是内存绑定的一个问题:
静态多态的内存分配:静态多态的函数地址在编译阶段就会绑定,就确定下来了,也就是说静态多态函数早绑定
动态多态的内存分配:动态多态的函数地址是在运行阶段才会绑定,也就是说动态多态的函数地址后绑定
比如下面的这个代码,和他的一个运行的结果:
#include
using namespace std;
class animal//基类
{
public:
void speak()
{
cout<<"animal speaks"<<endl;
}
};
class cat:public animal//派生类这里开始了
{
public:
void speak()
{
cout<<"cat speaks"<<endl;
}
};
void dospeak(animal &anima)
{
anima.speak();
}
int main()
{
cat Cat;
dospeak(Cat);
return 0;
}
先不要看结果猜猜是出现哪一个语句
好了公布答案
好的这里面发现了他走的是他的基类的那个函数,这个是为什么呢,这个就是可以理解为之前的先绑定了地址,也就是说他一开始的这个speak函数,它默认的绑定的地址就是基类的那个函数的地址,所以再次调用的时候他调用的就是基类的那个函数,暂时可以先这么理解,后面会有底层原理的一个解释。
然后我们言归正传,就是我们该如何解决这个问题呢/
如果我想调用的是派生类的那个函数,那么这里就是会用到了一个多态的概念,就是虚函数代码如下,只需要加一个virtual即可,咱们可以暂时理解为一开始不让他绑定,到后来运行的过程中再去找是谁绑定谁,应该走哪一个
代码如下:
#include
using namespace std;
class animal//基类
{
public:
virtual void speak()
{
cout<<"animal speaks"<<endl;
}
};
class cat:public animal//派生类这里开始了
{
public:
void speak()
{
cout<<"cat speaks"<<endl;
}
};
void dospeak(animal &anima)
{
anima.speak();
}
int main()
{
cat Cat;
dospeak(Cat);
return 0;
}
这里我们的这个就完成了,在平时我们可以习惯性的加上一个这个virtual,反正也没事要是出事了咱们再删嘿嘿
然后我们简单的总结一下动态多态需要的几个条件,第一个就是要满足一个继承条件,就是他们之间的关系得是继承关系,然后要涉及到函数的一个重写
这里重点一下子是函数的重写不是重载,重写是啥,是不管函数名,函数的参数,函数的列表,函数的返回值都一模一样,就里面的东西不一样叫做函数重写,这时候就会有动态多态出现~~我懒,我直接都加virtual在派生类里加也没啥太大影响~~然后让父类(基类)的指针指向子类(派生类)的对象这些一起就可以实现了动态多态
首先刚才的代码如果我们不加virtual 而是直接将那个类的数据空间输出,会发现是1是一个空类,但是当我们加上了这个virtual之后我们再次输出的时候我们会发现很神奇的我们的这个所占的空间他变成了4,也就是多了一个指针出来,这个指针是干嘛的呢?他是用来专门存储这个函数的入口地址的,然后当子类出现时,子类也会继承这个父类的这个,也就是说,子类也会产生一个指针存储了子类的这个函数的入口地址覆盖了父类的那个,然后在我们调用这个函数的时候我们同时会产生一个子类对象,就会出现这个指针和覆盖,所以我们可以正常调用我们所想调用的这个函数了
最后认识一下,我来自godhands