函数重写:子类定义与父类原型相同的函数,函数重写只发生在父类与子类之间
I'm Child...
I'm Parent...
父类被重写的函数子类依然会继承,默认情况子类重写的函数将隐藏父类中的函数,通过作用域分辨符::可访问到被隐藏的函数
函数重写遇上赋值兼容性原则
I'm Child...
I'm Parent...
I'm Parent... //打印三条I'm Child...更合理,但结果?
原因:C++与C同,均为静态编译型语言(类型静态,写程序时即确定好类型),编译时编译器自动根据指针类型判断指向的是一个什么样的对象,故编译器认为父类指针指向父类对象(根据赋值兼容性原则,这个假设也合理),由于程序没有运行,所以不可能知道父类指针指向具体是父类对象还是子类对象,从程序安全的角度, 编译器假设父类指针只指向父类对象,因此编译的结果为调用父类成员函数
------/
Master vs Boss
Master::eightSwordKill()
Boss::fight()
Master is killed...
New Master vs Boss
Master::eightSwordKill()
Boss::fight()
Master is killed...
面向对象新需求:根据实际对象类型来决定具体调用目标
如果父类指针指向的是父类对象则调用父类中定义的函数
如果父类指针指向的是子类对象则调用子类中定义的重写函数
多态:同样的调用语句有多种不同的表现形态
C++通过virtual关键字对多态进行支持, 用virtual声明的函数被重写后即展现多态特性
Master vs Boss
Master::eightSwordKill()
Boss::fight()
Master is killed...
New Master vs Boss
NewMaster::eightSwordKill()
Master::eightSwordKill() //?
Boss::fight()
Boss is killed...
class Parent
{
public:
void print()
{
cout<<"I'm Parent..."<<endl;
}
};
class Child : public Parent
{
public:
void print()
{
cout<<"I'm Child..."<<endl;
}
};
int main(int argc, char *argv[])
{
Child child;
child.print();
child.Parent::print();
return EXIT_SUCCESS;
}
结果:
I'm Child...
I'm Parent...
父类被重写的函数子类依然会继承,默认情况子类重写的函数将隐藏父类中的函数,通过作用域分辨符::可访问到被隐藏的函数
函数重写遇上赋值兼容性原则
class Parent
{
public:
void print()
{
cout<<"I'm Parent..."<<endl;
}
};
class Child : public Parent
{
public:
void print()
{
cout<<"I'm Child..."<<endl;
}
};
int main(int argc, char *argv[])
{
Child child;
Parent* pp = &child;
Parent& rp = child;
child.print();
pp->print();
rp.print();
return EXIT_SUCCESS;
}
结果:
I'm Child...
I'm Parent...
I'm Parent... //打印三条I'm Child...更合理,但结果?
原因:C++与C同,均为静态编译型语言(类型静态,写程序时即确定好类型),编译时编译器自动根据指针类型判断指向的是一个什么样的对象,故编译器认为父类指针指向父类对象(根据赋值兼容性原则,这个假设也合理),由于程序没有运行,所以不可能知道父类指针指向具体是父类对象还是子类对象,从程序安全的角度, 编译器假设父类指针只指向父类对象,因此编译的结果为调用父类成员函数
void howToPrint(Parent* p)
{
p->print(); //"child" or "parent"?
}
编译该函数时,编译器不知道指针p究竟指向什么,但编译器没理由报错,于是编译器认为最安全做法是编译到父类print函数,
因父类和子类都有相同的print函数
------/
class Boss
{
private:
static Boss* cInstance; //单例模式
Boss(){}
public:
static Boss* GetInstance()
{
if( cInstance == NULL )
{
cInstance = new Boss();
}
return cInstance;
}
int fight()
{
cout<<"Boss::fight()"<<endl;
return 10;
}
};
Boss* Boss::cInstance = NULL;
class Master
{
public:
int eightSwordKill()
{
cout<<"Master::eightSwordKill()"<<endl;
return 8;
}
};
class NewMaster : public Master
{
public:
int eightSwordKill()
{
cout<<"NewMaster::eightSwordKill()"<<endl;
return Master::eightSwordKill() * 2;
}
};
void fieldPK(Master* master, Boss* boss)
{
int k = master->eightSwordKill();
int b = boss->fight();
if( k < b )
{
cout<<"Master is killed..."<<endl;
}
else
{
cout<<"Boss is killed..."<<endl;
}
}
int main(int argc, char *argv[])
{
Boss* boss = Boss::GetInstance();
cout<<"Master vs Boss"<<endl;
Master master;
fieldPK(&master, boss);
cout<<"New Master vs Boss"<<endl;
NewMaster newMaster;
fieldPK(&newMaster, boss);
return EXIT_SUCCESS;
}
结果:
Master vs Boss
Master::eightSwordKill()
Boss::fight()
Master is killed...
New Master vs Boss
Master::eightSwordKill()
Boss::fight()
Master is killed...
面向对象新需求:根据实际对象类型来决定具体调用目标
如果父类指针指向的是父类对象则调用父类中定义的函数
如果父类指针指向的是子类对象则调用子类中定义的重写函数
多态:同样的调用语句有多种不同的表现形态
C++通过virtual关键字对多态进行支持, 用virtual声明的函数被重写后即展现多态特性
class Master
{
public:
virtual int eightSwordKill() //虚函数
{
cout<<"Master::eightSwordKill()"<<endl;
return 8;
}
};
class NewMaster : public Master
{
public:
virtual int eightSwordKill() //也加virtual增强可读性
{
cout<<"NewMaster::eightSwordKill()"<<endl;
return Master::eightSwordKill() * 2;
}
};
结果:
Master vs Boss
Master::eightSwordKill()
Boss::fight()
Master is killed...
New Master vs Boss
NewMaster::eightSwordKill()
Master::eightSwordKill() //?
Boss::fight()
Boss is killed...