先几句话:
多态的三个必要条件:
1.存在继承
2.虚方法重写
3.父类(指针或者引用)指向子类对象
就一堆代码..
#include <iostream>
using namespace std;
class CWorm
{
public:
CWorm() { cout << "CWorm" << endl; }
virtual ~CWorm() { cout << "~CWorm" << endl; }
public:
virtual void speak()
{
cout << "CWorm::speak/n";
}
};
class CAnt: public CWorm
{
public:
CAnt() { cout << "CAnt" << endl; }
virtual ~CAnt() { cout << "~CAnt" << endl; }
public:
virtual void speak()
{
cout << "CAnt::speak/n";
}
};
class CSpider: public CWorm
{
public:
CSpider() { cout << "CSpider" << endl; }
virtual ~CSpider() { cout << "~CSpider" << endl; }
public:
virtual void speak()
{
cout << "CSpider::speak/n";
}
};
class CNormal
{
public:
CNormal() { cout << "CNormal" << endl; }
~CNormal() { cout << "~CNormal" << endl; }
public:
virtual void speak()
{
cout << "CNormal::speak/n";
}
};
class CVirtual: public CNormal
{
public:
CVirtual() { cout << "CVirtual" << endl; }
~CVirtual() { cout << "~CVirtual" << endl; }
};
class CVirtualEX: public CNormal
{
public:
CVirtualEX() { cout << "CVirtualEX" << endl; }
~CVirtualEX() { cout << "~CVirtualEX" << endl; }
};
class CNormal2
{
public:
CNormal2() { cout << "CNormal2" << endl; }
virtual ~CNormal2() { cout << "~CNormal2" << endl; }
public:
virtual void speak()
{
cout << "CNormal2::speak/n";
}
};
class CVirtual2: public CNormal2
{
public:
CVirtual2() { cout << "CVirtual2" << endl; }
~CVirtual2() { cout << "~CVirtual2" << endl; }
};
class CVirtualEX2: public CNormal2
{
public:
CVirtualEX2() { cout << "CVirtualEX2" << endl; }
~CVirtualEX2() { cout << "~CVirtualEX2" << endl; }
};
void Call1(CWorm w)
{
w.speak();
}
void Call2(CWorm &w)
{
w.speak();
}
void Call3(CWorm* pw)
{
pw->speak();
}
class Cbak
{
public:
Cbak() { cout << "Cbak" << endl; }
virtual ~Cbak() { cout << "~Cbak" << endl; }
public:
virtual Cbak speak()
{
cout << "Cbak::speak/n";
return *this;
}
};
int main()
{
/*
CWorm w;
cout << "---------------CWorm w;" << endl;
CSpider s;
cout << "---------------CSpider s;" << endl;
CAnt a;
cout << "---------------CAnt a;" << endl;
// 会调用拷贝构造函数,产生临时对象CWorm t; 这时虚函数表指针不会被拷贝,
// 所以使得函数内部使用的是临时对象t.调用的是CWorm的speak
// 默认并且尽量使用静态联编,也就是编译器编译时就确定函数的地址,不使用寻址间接调用
// 在主程序产生了析构函数
Call1(s);
cout << "---------------Call1(s);" << endl;
Call2(s);
cout << "---------------Call2(s);" << endl;
Call3(&s);
cout << "---------------Call3(&s);" << endl;
CNormal* pcn = new CVirtual;
delete (CVirtual*)(unsigned long)pcn;
// 看起来编译器产生代码的时候,根据delete 目标的对象类型来产生delete代码,不去研究是目标实际的类型.
CNormal* pcn1 = new CVirtual;
delete (CVirtualEX*)(unsigned long)pcn1;
cout << "---------------delete pcn;" << endl;
CNormal2* pcn20 = new CVirtual2;
delete pcn20;
CNormal2* pcn21 = new CVirtual2;
delete (CVirtual2*)(unsigned long)pcn21;
CNormal2* pcn22 = new CVirtual2;
delete (CVirtualEX2*)(unsigned long)pcn22;
CNormal2* pcn23 = new CVirtual2;
delete (CSpider*)pcn23;
//CNormal* pcn1 = new CVirtual;
//delete (CNormal*)(unsigned long)pcn1;
//CNormal* pcn2 = new CVirtual;
//delete pcn2;
cout << "---------------delete pcn2;" << endl;
//CNormal2* pcn211 = (CNormal2*)new CVirtual;
//delete pcn211;
cout << "---------------delete pcn1 & pcn2;" << endl;
// 看起来编译器产生代码的时候,根据delete 目标的对象类型是否包含虚函数来决定是否根据有虚函数的方式来
// 来产生delete代码
CNormal* pcn112 = (CNormal*)new CVirtual2;
delete pcn112;
CVirtualEX* pcn113 = (CVirtualEX*)new CVirtual2;
delete pcn113;
CSpider* pcn114 = (CSpider*)new CVirtual2;
delete pcn114;
char* pcn115 = (char*)new CVirtual2;
delete [] pcn115;
cout << "---------------delete pcn2 & pcn1;" << endl;
*/
/*
CWorm *pw = new CWorm;
pw->speak();
CWorm *pw2 = new CSpider;
pw2->speak();
CSpider s;
CWorm *pw3 = &s;
pw3->speak();
CWorm w = s;
w.speak();
CWorm w2;
memcpy(&w2,pw3,sizeof(s));
((CWorm*)(unsigned long)&w2)->speak(); // 采用了动态联编
cout << "---------------((CWorm*)(char*)&w2)->speak();" << endl;
//((CNormal*)&w2)->speak(); // 因为没有虚函数表,其实就调用了,Spider的析构函数,运行完后堆栈检查通不过
cout << "---------------((CNormal*)&w2)->speak();" << endl;
((CNormal2*)&w2)->speak(); // 能正确调用Spider的speak
cout << "---------------((CNormal2*)&w2)->speak();" << endl;
w2.speak(); // 采用了静态联编
cout << "---------------w2.speak();" << endl;
CNormal cn;
CNormal* pcn = new CNormal;
CVirtual* pcv = new CVirtual;
cout << "CNormal: cn::sizeof "<< sizeof(cn) << endl;
cout << "CNormal::sizeof "<< sizeof(CNormal) << endl;
cout << "CWorm::sizeof "<< sizeof(CWorm) << endl;
cout << "CSpider::sizeof "<< sizeof(CSpider) << endl;
delete pcv;
cout << "---- delete CVirtual ------"<< endl;
delete pcn;
cout << "---- delete CNormal ------"<< endl;
delete pw2;
delete pw;
*/
Cbak b;
Cbak* c = &(b.speak());// 在speak内部调用了拷贝构造函数产生临时对象,在主程序产生了析构函数
cout << "---- Cbak* c = &(b.speak()); ------"<< endl;
return 0;
}