1、多态的引入
①人类作为基类,然后有英国人、中国人…
注意:以下实例执行结果为
#include
#include
#include
using namespace std;
class Human {
public:
void eating(void) { cout<<"use hand to eat"<<endl; }
};
class Englishman : public Human {
public:
void eating(void) { cout<<"use knife to eat"<<endl; } //覆写
};
class Chinese : public Human {
public:
void eating(void) { cout<<"use chopsticks to eat"<<endl; } //覆写
};
void test_eating(Human& h)
{
h.eating();
}
int main(int argc, char **argv)
{
Human h;
Englishman e;
Chinese c;
test_eating(h);
test_eating(e);
test_eating(c);
return 0;
}
2、上述实例结果显然不是我们想要的
注意:要分辨(引入虚函数让系统帮我们分辨,关键词virtual)他们是什么人,然后调用他们自己的吃饭方式
#include
#include
#include
using namespace std;
class Human {
private:
int a;
public:
virtual void eating(void) { cout<<"use hand to eat"<<endl; }
};
class Englishman : public Human {
public:
void eating(void) { cout<<"use knife to eat"<<endl; }
};
class Chinese : public Human {
public:
void eating(void) { cout<<"use chopsticks to eat"<<endl; }
};
void test_eating(Human& h)
{
h.eating();
}
int main(int argc, char **argv)
{
Human h;
Englishman e;
Chinese c;
test_eating(h);
test_eating(e);
test_eating(c);
cout<<"sizeof(Human) = "<<sizeof(h)<<endl;
cout<<"sizeof(Englishman) = "<<sizeof(e)<<endl;
cout<<"sizeof(Chinese) = "<<sizeof(c)<<endl;
return 0;
}
3、多态机制:静态联编(非虚函数,在编译好时就已经确定好了调用哪一个),动态联编(虚函数,在运行的时候才确定好调用哪一个函数)
①动态联编的实现过程:如果类里面有虚函数,那么他的对象里面有一个指针指向虚函数表,然后在调用函数的时候就会通过这个指针找到虚函数表,然后调用里面的虚函数 ,
②加入定义虚函数的关键词virtual,空间会变大(多了12字节,就是多的这个指针指向这个虚函数表 )
4、使用多态时有哪些需要注意的
①void test_eating(Human& h)或者void test_eating(Human* h)使用指针或是引用来使用对象的时候,才会有多态
②void test_eating(h)传值时,无多态
③只有类的成员函数才能声明为虚函数
④静态成员函数不能是虚函数
⑤内联函数不能是虚函数
⑥构造函数不能是虚函数
⑦析构函数一般都声明为虚函数
⑧重载函数参数不同,不可以设为虚函数
⑨覆写函数参数和返回值相同,可以设为虚函数(返回值有点例外,当返回值是当前对象的指针或引用的时候也可以设为虚函数)
5、析构函数一般都声明为虚函数
注意:~Englishman()和 ~Chinese()输出一下结果这样显然析构函数是不对的,
需要将每个类中的析构函数声明为虚函数virtual ~Englishman()和virtual ~Chinese()
解释:释放派生类后还需要释放派生类的基类
#include
#include
#include
using namespace std;
class Human {
private:
int a;
public:
virtual void eating(void) { cout<<"use hand to eat"<<endl; }
virtual ~Human() { cout<<"~Human()"<<endl; }
};
class Englishman : public Human {
public:
void eating(void) { cout<<"use knife to eat"<<endl; }
virtual ~Englishman() { cout<<"~Englishman()"<<endl; }
};
class Chinese : public Human {
public:
void eating(void) { cout<<"use chopsticks to eat"<<endl; }
virtual ~Chinese() { cout<<"~Chinese()"<<endl; }
};
void test_eating(Human h)
{
h.eating();
}
int main(int argc, char **argv)
{
Human* h = new Human;
Englishman* e = new Englishman;
Chinese* c = new Chinese;
Human *p[3] = {h, e, c};
int i;
for (i = 0; i < 3; i++)
{
p[i]->eating();
delete p[i];
}
return 0;
}
6、覆写函数参数和返回值相同,可以设为虚函数(返回值有点例外,当返回值是当前对象的指针或引用的时候也可以设为虚函数)
注意:设置为虚函数,参数名和参数一定要一样,返回值也应该要一样(但是可以是当前对象的指针或引用)
#include
#include
#include
using namespace std;
class Human {
private:
int a;
public:
virtual void eating(void) { cout<<"use hand to eat"<<endl; }
virtual ~Human() { cout<<"~Human()"<<endl; }
virtual Human* test(void) {cout<<"Human's test"<<endl; return this; }
};
class Englishman : public Human {
public:
void eating(void) { cout<<"use knife to eat"<<endl; }
virtual ~Englishman() { cout<<"~Englishman()"<<endl; }
virtual Englishman* test(void) {cout<<"Englishman's test"<<endl; return this; }
};
class Chinese : public Human {
public:
void eating(void) { cout<<"use chopsticks to eat"<<endl; }
virtual ~Chinese() { cout<<"~Chinese()"<<endl; }
virtual Chinese* test(void) {cout<<"Chinese's test"<<endl; return this; }
};
void test_eating(Human& h)
{
h.eating();
}
void test_return(Human& h)
{
h.test();
}