多态:
1.重载多态----函数重载,运算符重载
2.包含多态----virtual函数
3.参数多态----模板
4.强制多态----强制类型转换
对(FUN)* int* *int * &a 的理解
class A
{
public:
virtual void fa() { cout << "A::fa" << endl; }
virtual void fb() { cout << "A::fb" << endl; }
virtual void fc() { cout << "A::fc" << endl; }
};
int main()
{
cout << sizeof(A);//4
}
如果一个类包含了虚函数,不管有多少个虚函数,只增加了一个指针的大小,
多了一个指针VPtr,指向虚表,虚表里面存储虚表中虚函数的入口地址。
A a;
typedef void(*FUN)();//声明一个函数指针
FUN pf= NULL;//声明了一个函数pf,FUN pf; /*等价于void pf();*/
pf = (FUN) * ((int*)(*(int*)(&a)));//a.fa();
pf();
pf = (FUN) * ((int*)(*(int*)(&a)) + 1);//a.fb();
pf();
pf = (FUN) * ((int*)(*(int*)(&a)) + 2);// a.fc();
pf();
1、(int )(&b) 表示对象b中指向虚函数table的指针的地址。
2、((int )(&b)) 表示对象b中指向虚函数table的指针,即虚函数table的首地址。
3、(int )(((int )(&b)))+0 表示对象b中指向虚函数table的第一个表项的地址,注意该表项的内容为第一个虚函数的地址。
4、((int )(((int )(&b)))+0) 表示对象b中指向虚函数table的第一个表项的内容----即第一个虚函数的地址。
将其赋值给 pFun,便可以调用第一个虚函数,pFun = (Fun)(((int )(((int )(&b)))+0) )
存在同名同参的函数
注意这里A类和B类的成员中都有名为fa()的同名同参函数
class A
{
public:
virtual void fa() { cout << "A::fa" << endl; }
virtual void ga() { cout << "A::ga" << endl; }
virtual void ha() { cout << "A::ha" << endl; }
};
class B :public A
{
public:
virtual void fa() { cout << "B::fa" << endl; }//同名同参的虚函数,覆盖
virtual void gb() { cout << "B::gb" << endl; }
virtual void hb() { cout << "B::hc" << endl; }
};
void test(A a)
{
a.fa();
}
int main()
{
B b;
typedef void(*FUN)();
FUN pf = NULL;
pf = (FUN) *( (int*)*(int*)(&b));
pf();
pf = (FUN) * ((int*)*(int*)(&b)+1);
pf();
pf = (FUN) * ((int*)*(int*)(&b) + 2);
pf();
pf = (FUN) * ((int*)*(int*)(&b) + 3);
pf();
pf = (FUN) * ((int*)*(int*)(&b) + 4);
pf();
}
为什么第一行应该输出的是A::fa为什么会变成B::fa呢?
因为子类B拥有和基类A同名同参的fa函数,而在B类中重写并覆盖原来的A::fa()
存在多继承类的虚函数
{
public:
virtual void fa() { cout << "A::fa" << endl; }
virtual void ha() { cout << "A::ha" << endl; }
};
class B
{
public:
virtual void fb() { cout << "B::fb" << endl; }
virtual void hb() { cout << "B::hb" << endl; }
};
class C
{
public:
virtual void fc() { cout << "C::fc" << endl; }
virtual void hc() { cout << "C::hc" << endl; }
};
class D :public A, public B, public C
{
public:
virtual void fd() { cout << "D::fd" << endl; }
virtual void hd() { cout << "D::hd" << endl; }
};
void main()
{
cout << sizeof(D) << endl;
D d;
typedef void(*FUN)();
FUN pf = NULL;
pf = (FUN) * ((int*)*(int*)(&d));
pf();
pf = (FUN) * ((int*)*(int*)(&d) + 1);
pf();
pf = (FUN) * ((int*)*(int*)(&d) + 2);
pf();
pf = (FUN) * ((int*)*(int*)(&d) + 3);
pf();
pf = (FUN) * ((int*)*(int*)((int*)(&d) + 1));
pf();
pf = (FUN) * ((int*)*(int*)((int*)(&d) + 1)+1);
pf();
pf = (FUN) * ((int*)*(int*)((int*)(&d) + 2));
pf();
pf = (FUN) * ((int*)*(int*)((int*)(&d) + 2) + 1);
pf();
}
联编
覆盖(重写)
1.最少两个类,必须是父子关系
2,同名同参虚函数,基类写了virtual,子类可以不写
多态的条件:
1.满足覆盖
2.基类的指针或者引用指向基类对象或派生类对象
联编(捆绑,绑定)–——函数调用和函数体联系的过程
早联编–编译时
晚联编–运行时
class A
{
public:
virtual void fn() { cout << "A::fn" << endl; }
};
class B :public A
{
public:
virtual void fn() { cout << "B::fn" << endl; }
};
void test(A aa)//(A &aa)引用传递则可以输出b.fn
{
aa.fn();//
}
void test1(A *p)
{
p->fn();
}
int main()
{
A a;
B b;
a.fn();
b.fn();
test(a);
test(b);//为什么输出不是“b.fn"呢,因为函数test()里参数A aa已经和fn函数捆绑
test1(&a);
test1(&b);
}
为什么test(b)时输出的不是B::fn(),而是A::fn()?
因为函数test()里形参A aa已经和fn函数捆绑,默认传过来的值都是A类型的,所以调用的是A类的fn函数。
解决办法:
因为test(a)和test(b)都是值传递,所以可以采取引用传递 test1(&a)和test1(&b)来达到目的