虚函数最大的好处是可以保持驱动程序的变量数据在增加派生类后可以不发生修改,已经统一程序接口,如:
1
class
B
{
public:
virtual
void
Run()=0;
};
class
A
:
public
B
{
public:
virtual
void
Run(){
cout<<"run
A"<<endl;
}
};
class
C:
public
B
{
public:
virtual
void
Run(){
cout<<"run
B"<<endl;
}
};
现在有一个驱动模块,如类
Drv
class
Drv
{
public:
void
Execute()
{
b->Run();
}
private:
B
b;
};
即使以后派生类扩展了,这个驱动程序的数据程序,已经主要函数基本不做修改,使得出错率降低。如果不用虚函数,可能的代码为:
class
Drv
{
public:
void
Execute()
{
switch(a)
{
case
0:
aRun();
break;
case
1:
cRun();
break;
//以后可能还要增加其它派生类对象
}
}
private:
int
sel
A
a;
B
b;
//以后可能还要增加其它派生类对象
};
显然每增加一个派生类,就要对上面做多处修改!!!
2
通用接口,如:
void
Execute(B
&b)
{
bRun();
}
这样可以使用如:
A
a;
Execute(a);
C
c;
Execute(c);
使得程序降低,否则需要定义给每个类为参数的函数,如:
void
Execute(A
&a)
{
aRun();
}
void
Execute(C
&c)
{
cRun();
}
上面的两个例子可以看到虚函数的好处!!
什么是多态?
可以这么回答:
父类引用
引用子类对象
父类和子类有同名的覆盖方法
通过父类引用调用这个重写的方法的时候。多数的话就可以称为多态,单数可以说运行时绑定。
使用多态有什么好处?
类调用者对类的使用成本进一步降低
封装是让类的调用者不需要知道类的实现细节,多态能让类的调用者连这个类的类型是什么都不必知道,只需要知道这个对象具有某个方法即可。因此,多态可以理解成是封装的更进一步,让类调用者对类的使用成本进一步降低。
能够降低代码的“圈复杂度”,避免使用大量的if-else
多态在代码中的体现:
输出结果:
猫吃鱼
猫吃鱼(因为描述的是真正的是一只猫)
拓展:
多态性:同一 *** 作作用于不同的对象,可以用不同的解释,产生不同的执行结果,这就是多态性。
多态性通过派生类覆写基类中的虚函数的方法来实现。
多态性分为两种,一种是编译时的多态性,一种是运行时的多态性。
编译时的多态性:编译时多态是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数,返回的类型等信息决定实现何种 *** 作。
运行时的多态性:运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种 *** 作。
Systemoutprintln();是用重载来实现的。而不是多态。
Systemoutprintln();会默认调用toString方法
如果是Systemoutprintln(11);
请看源码
public void println(int x) {
synchronized (this) {
print(x);
newLine();
}
}
---------
public void print(int i) {
write(StringvalueOf(i));
}
----
public static String valueOf(int i) {
return IntegertoString(i, 10);//这里调用了toString方法
}
public static String valueOf(long l) {
return LongtoString(l, 10);
}
很多
-----------------------------------------------
如果是Systemoutprintln(new Object());
public void println(Object x) {
String s = StringvalueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
public static String valueOf(Object obj) {
return (obj == null) "null" : objtoString();//这里调用了toString方法
}
----------------------------
接下来你的问题
不修改toString方法就默认输出类名和内存地址,但是类是可以自己随便定义的,请问这个方法的多态是如何实现的。
你重写了toString,而
public String toString() {
return getClass()getName() + "@" + IntegertoHexString(hashCode());
}
是动态绑定,所以他调用new出的类型的方法
这里才是多态
静态联编支持的多态性称为编译时的多态性,也称静态多态性,它是通过函数重载和运算符重载实现的。
动态联编支持的多态性称为运行时的多态性,也称动态多态性,它是通过继承和虚函数实现的。
不是使用了虚函数就能实现运行时的多态性,实现运行时多态性要满足以下4个条件:
要有一个继承层次
2在基类要定义虚函数
3在派生类中要对基类中的虚函数进行重定义
4要通过基类指针(或基类引用)来调用虚函数
多态是用基类指针来实现的,而使用new关键字,动态分配内存返回给pGame的就是类型指针。
如果采用静态分配如 CBlockGame game(hInstance,hWnd); 得到的game是一个对象,而非指针。
构造函数在new的时候当然会运行一次,要对新对象进行初始化。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)