1.多态定义
之所以引入虚函数,是为了引入多态
多态就是使用相同的调用方法,对不同的对象,它会调用不同类里面实现的函数
#include <iostream>
#include <string.h>
#include <unistd.h>
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;
}
运行结果:
use hand to eat
use hand to eat
use hand to eat
2.虚函数
应该在 test_eating 中分辨它属于哪一个对象,是英国人还是中国人,让系统编译器帮忙分辨
Human中的 eating 加上virtual 变成虚函数
派生类继承它,也就变成了虚函数,可以加 virtual,也可以不加 virtual
#include <iostream>
#include <string.h>
#include <unistd.h>
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;
}
执行结果:
use hand to eat
use knife to eat
use chopsticks to eat
静态联编:如果不是 virtual虚函数,test_eating 在编译的时候就确定好 h.eating 调用哪一个类里面的 eating函数,
动态联编:在运行的时候才知道调用哪一个函数
3.使用引用或指针来使用对象时,才有多态;传值时,无多态
使用引用或指针来使用对象时,才有多态;传值时,无多态
a.只有类的成员函数才能声明为虚函数
b.静态成员函数不能是虚函数
c.内联函数不能是虚函数
d.构造函数不能是虚函数
e.析构函数一般声明为虚函数
f.重载:函数参数不同,不能设为虚函数
覆写:函数参数、返回值相同,可以设为虚函数
g.返回值例外
函数参数相同,但是返回值是当前对象的指针或引用时,也可以设为虚函数
#include <iostream>
#include <string.h>
#include <unistd.h>
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;
}
运行结果:
use hand to eat
use hand to eat
use hand to eat
强制转化之后,就只剩下基类部分,没有指针了,所以传值时候只能使用静态联编
4.析构函数一般声明为虚函数
#include <iostream>
#include <string.h>
#include <unistd.h>
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;
}
5.返回值例外
函数参数相同,但是返回值是当前对象的指针或引用时,也可以设为虚函数
#include <iostream>
#include <string.h>
#include <unistd.h>
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 void test(void) {cout<<"Human's test"<<endl; }
};
class Englishman : public Human {
public:
void eating(void) { cout<<"use knife to eat"<<endl; }
virtual ~Englishman() { cout<<"~Englishman()"<<endl; }
virtual int test(void) {cout<<"Englishman's test"<<endl; return 1; }
};
class Chinese : public Human {
public:
void eating(void) { cout<<"use chopsticks to eat"<<endl; }
virtual ~Chinese() { cout<<"~Chinese()"<<endl; }
virtual int test(void) {cout<<"Chinese's test"<<endl; return 1; }
};
void test_eating(Human& h)
{
h.eating();
}
void test_return(Human& h)
{
h.test();
}
int main(int argc, char **argv)
{
Human h;
Englishman e;
Chinese c;
test_return(h);
test_return(e);
test_return(c);
return 0;
}
返回值不是指针且不同,编译不能通过
#include <iostream>
#include <string.h>
#include <unistd.h>
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();
}
int main(int argc, char **argv)
{
Human h;
Englishman e;
Chinese c;
test_return(h);
test_return(e);
test_return(c);
return 0;
}