隻要成員名稱一樣(即使base classes和derived classes内的函數有不同的參數類型,而且不論函數是vitual或non-virtual),繼承類中的名稱就會遮掩base class内的名稱。
表現如下:
#include<iostream>
using namespace std;
class Base
{
public:
void mf1()
{cout<<"Base::mf1"<<endl;}
void mf1(int a)
{cout<<"Base::mf1(int)"<<endl;}
void mf2()
{cout<<"Base::mf2"<<endl;}
};
class Derived:public Base
{
public:
void mf1()
{cout<<"Derived::mf1"<<endl;}
void mf2()
{cout<<"Derived::mf2"<<endl;}
void CallBase()
{Base::mf1();}
};
int main()
{
Derived d;
d.mf1();
d.CallBase();//正确。如果在類體内通過Base::mf1();則可調用父類的同名函數。
d.mf1(1);//報錯 no matching function for call to `Derived::mf1(int)'
//candidates are: void Derived::mf1()
getchar();
}
在Base中有mf1(int )函數,但是在Derived類中,已經重載了mf1函數,是以把Base中的所有同名函數都遮掩了。隻有mf1()可以通過Derived對象直接調用。
可以Derived類體中直接通過其它函數調用Base中沒有被同名遮掩的成員函數,或者通過Derived對象都可以直接調用Base中沒有被同名遮掩的成員函數。(前提是滿足public\protected\private的繼承限制)。例:
#include<iostream>
using namespace std;
class Base
{
public:
void init()
{cout<<"Base::init"<<endl;}
void mf1(int a)
{cout<<"Base::mf1(int)"<<endl;}
void mf2()
{cout<<"Base::mf2"<<endl;}
};
class Derived:public Base
{
public:
void CallBase()
{init();}
};
int main()
{
Derived d;
d.CallBase();//正确
d.init();//正确
getchar();
}
輸出:
一個virtual函數的例子:
#include<iostream>
using namespace std;
class Base
{
public:
void init()
{mf1();}
private:
virtual void mf1()
{cout<<"Base::mf1"<<endl;}
};
class Derived:public Base
{
private:
virtual void mf1()
{cout<<"Derived::mf1"<<endl;}
};
int main()
{
Derived d;
d.init();//正确
Base b;
b.init();
Base &tb=d;
tb.init();
getchar();
}
通過基類的init()通路不同類型的mf1(),實作多态。
如果private繼承則:
#include<iostream>
using namespace std;
class Base
{
public:
void init()
{mf1();}
private:
virtual void mf1()
{cout<<"Base::mf1"<<endl;}
};
class Derived:private Base
{
private:
virtual void mf1()
{cout<<"Derived::mf1"<<endl;}
};
int main()
{
Derived d;
// d.init();//報錯:`void Base::init()' is inaccessible
//`Base' is not an accessible base of `Derived'
Base b;//正确
b.init();//正确
// Base &tb=d;//報錯 `Base' is not an accessible base of `Derived'
// tb.init();
getchar();
}
上面代碼再變化,把d存到Base b中,造成切割後:
#include<iostream>
using namespace std;
class Base
{
public:
void init()
{mf1();}
private:
virtual void mf1()
{cout<<"Base::mf1"<<endl;}
};
class Derived:public Base
{
private:
virtual void mf1()
{cout<<"Derived::mf1"<<endl;}
};
int main()
{
Derived d;
Base b=d;//Derived部分被切割掉了,結果隻剩下基類的mf1可供選擇了。
b.init();
getchar();
}
結果:
通過using聲明式讓被遮掩的成員函數重見天日:
#include<iostream>
using namespace std;
class Base
{
public:
void mf1()
{cout<<"Base::mf1"<<endl;}
void mf1(int x)
{cout<<"Base::mf1(int)"<<endl;}
};
class Derived:public Base
{
public:
using Base::mf1;//這裡用了using 聲明式
void mf1()
{cout<<"Derived::mf1"<<endl;}
};
int main()
{
Derived d;
d.mf1();
d.mf1(1);//有了using Base::mf1 就Derived對象就可以通路基類中被遮掩的同名函數了
getchar();
}
通過using聲明式,在Derived類中引入基類被隐藏的函數。
通過轉交函數讓基類中的函數重見天日:
#include<iostream>
using namespace std;
class Base
{
public:
void mf1()
{cout<<"Base::mf1"<<endl;}
void mf1(int x)
{cout<<"Base::mf1(int)"<<endl;}
};
class Derived:public Base
{
public:
void mf1()
{Base::mf1();} //轉交
};
int main()
{
Derived d;
d.mf1();
getchar();
}
結果:
個人補充:直接加上作用域符來顯式調用基類同名函數
如:
#include<iostream>
using namespace std;
class A
{
public:
void fun(){cout<<"A::fun"<<endl;}
};
class B:public A
{
public:
void fun(){cout<<"B::fun"<<endl;}
};
void Test()
{
B d;
d.fun();
d.A::fun();
}
int main()
{
Test();
getchar();
return 0;
}
結果: