这三个概念是讨论的函数名相同的情况,不要后面要问怎么函数名不同的时候不讨论呢?那你现在最好要确定下函数名不同值得讨论吗?
-----------------------------------------------------------------------------------------------------------------------------------
这个B里面增加什么东西会是上面的概念呢?
-----------------------------------------------------------------
重载:同一个类中定义的函数名相同,参数不同的方法。如果和继承的函数的函数名相同,就要涉及到重写和隐藏。其实不应该拿到这里来讨论的,因为它是指在同一个类中定义的。
----------------------------------------------------------------
重写:这个就涉及到大家常用的virtual关键字了。也就是基类函数用virtual修饰,子类中定义一个函数与其同名,而且参数相同。这里就是所谓的多态。如果您还不知道多态,请百度下。 当基类中的某个函数virtual后,子类创建基类对象,并用子类的重写的方法放入基类本来分好的代码段中,把以前的代码覆盖掉,也就是把函数重写了。其实这就是所谓的动态绑定技术。这样的话无论你是用基类指针还是派生类指针访问该函数,执行的都是子类中重新写的代码。
----------------------------------------------------------------
隐藏: 什么是隐藏?看代码
例1
class A
{
public:
void fun1()
{
cout<<"A:fun1"<<endl;
}
};
class B:public A
{
public:
};
int _tmain(int argc, _TCHAR* argv[])
{
A* ap=new B;
B* bp=(B*)ap;
ap->fun1();
bp->fun1();
return 0;
}
结果:A:fun1
A:fun1
这是正常情况下,B继承了A的fun1,所以用两种类型的指针调用的都是同一个fun1。下面在B中分3种情况加一个同名函数。
例2
class A
{
public:
void fun1()
{
cout<<"A:fun1"<<endl;
}
};
class B:public A
{
public:
void fun1()
{
cout<<"B:fun1"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* ap=new B;
B* bp=(B*)ap;
ap->fun1();
bp->fun1();
return 0;
}
结果:A:fun1
B:fun1
子类同名函数,参数相同,但基类函数没有virtual,这个时候是隐藏。用子类的指针只能访问子类的那个fun1,不能访问继承自基类的fun1,其实它仍然存在与基类的代码段中,
因为用A类型指针能头访问它。这也是隐藏名字的由来,基类的fun1对子类指针隐藏了,躲猫猫了,但仍然存在,要通过基类指针访问。
例3
class A
{
public:
void fun1()
{
cout<<"A:fun1"<<endl;
}
};
class B:public A
{
public:
void fun1(int i)
{
cout<<"B:fun1"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* ap=new B;
B* bp=(B*)ap;
ap->fun1();
bp->fun1(); //这里编译报错
return 0;
}
结果:error C2660: “B::fun1” : 函数不接受 0 个参数
基类同名函数非virtual,子类参数不同。那么当用子类指针进行访问继承自A的fun1时,会访问不了,报错。当你注释掉以后,用A的指针还是能访问的。
例4
class A
{
public:
virtual void fun1()
{
cout<<"A:fun1"<<endl;
}
};
class B:public A
{
public:
void fun1(int i)
{
cout<<"B:fun1 int"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* ap=new B;
B* bp=(B*)ap;
ap->fun1();
bp->fun1();
return 0;
}
结果:和上一种情况一样。
基类同名函数是virtual的,子类定义了一个同名参数不同的,但还是隐藏的。
结论:子类和基类定义同名函数的总共4种情况(virtual两种,参数两种,总共2*2)都讨论过了。综上所述,当基类的某函数声明为virtual,使用动态绑定技术,当最终创建子类对象的时候,如果子类种有同名且参数相同即完全一样的函数的时候,这个时候基类的virtual函数代码才最终确定。也实现了函数的重写。当创建子类对象的时候,如果没碰到同名参数相同的函数,会使用基类定义的代码。这个时候如果子类也定义了一个同名的函数,那么会隐藏掉基类的同名函数。这就是4种情况的另外3种情况。
补充:
class A
{
public:
virtual void show()
{
cout<<"ok in a"<<endl;
}
};
class B :public A
{
void show()
{
cout<<"ok in b"<<endl;
}
};
int main()
{
B *bp=new B;
A *ap=(A*)bp;
ap->show();
//bp->show(); //出现编译错误 error C2248: “B::show” : 无法访问 private 成员(在“B”类中声明)
}
出现编译错误,是因为B中的show()是private的。bp调用时权限是B定义的,ap调用权限是A定义的。