如果发生了基类与派生类中有成员名字相同时,那么他们之间肯定是要产生关系的,所以这就涉及到了成员的重载、隐藏和覆盖。
例子
我们现在先制定如下案例,我们先构造一个基类Base,其中有show()和show(int)两个方法:
class Base {
public:
Base(int data = 10) : ma(data) { }
void show() { cout << "Base::show()" << endl; }
void show(int) { cout << "Base::sjow(int)" << endl; }
protected:
int ma;
};
现在我们定义一个派生类,继承基类,然后我们在main函数中初始化一个派生类对象实例,通过该实例调用show和show(int):
class Derive : public Base {
public:
Derive(int data = 20) : Base(data), mb(data) { }
private:
int mb;
};
int main () {
Derive d;
d.show();
d.show(10);
return 0;
}
//打印结果:
//Base::show()
//Base::show(int)
重载 和 隐藏
重载
现在我们在派生类中也定义show()方法,但是不定义show(int):
class Derive : public Base {
public:
Derive(int data = 20) : Base(data), mb(data) { }
void show() { cout << "Base::show()" << endl; }
private:
int mb;
};
我们仍然在main函数中做如下调用:
int main () {
Derive d;
d.show();
//too many arguments to function call, expected 0, have 1; did you mean 'Base::show'?
//d.show(10);//报错!
return 0;
}
我们从提示可以看出,编译器并不会主动调用基类中的show(int),而是报错。
那么就是说,基类和派生类的成员名字是可以相同的,不会产生冲突,因为作用域不一样,那么名字相同的成员,就要产生一定的关系:
- 重载关系
- 一组函数要重载,必须处在同一作用域中,而且函数名字相同,参数列表不同。所以基类中的show()和show(int)属于重载关系,派生类中的show()和基类中的show()压根就不属于重载关系,因为作用域不同啊!
隐藏
在继承结构当中,派生类的同名成员,会把基类的同名成员给隐藏掉,所以上文中,派生类的show()把基类的show()和show(int)都隐藏掉了,这是在编译阶段就决定的。
其实,我们只要在main函数中这样:
d.Base::show(10);
就可以完成调用了。所以,隐藏其实指的是:作用域的隐藏。
覆盖
覆盖的概念设计到虚函数和多态。
覆盖即基类和派生类的方法,返回值、函数名以及参数列表都相同,而且基类的方法是虚函数,
那么派生类的方法就自动处理成虚函数,他们之间成为覆盖关系。
class Base {
public:
Base(int data = 10) : ma(data) { }
virtual void show() { cout << "Base::show()" << endl; }
virtual void show(int) { cout << "Base::show(int)" << endl; }
protected:
int ma;
};
class Derive : public Base {
public:
Derive(int data = 20) : Base(data), mb(data) {}
void show() {cout << "Derive::shwo()" << endl; }
private:
int mb;
};
int main () {
Derive d(50);
d.show();
}
此时,我们调用的就是Derive类的show方法。