注意:本文中代碼均使用 Qt 開發(fā)編譯環(huán)境
作用域分辨符纸兔,就是經(jīng)常見到的“::”舆逃,他可以用來限定要訪問的成員所在的類的名稱伤疙,一般形式是:
基類名::成員名; // 數(shù)據(jù)成員
基類名::成員名(參數(shù)表); // 函數(shù)成員
在沒有虛函數(shù)的情況下兵睛,如果派生類中聲明了與基類成員函數(shù)同名的新函數(shù),即使函數(shù)的參數(shù)表不相同奋渔,從基類繼承的同名函數(shù)的所有重載形式也都會被隱藏。如果想要訪問被隱藏的成員壮啊,就需要使用作用域分辨符和基類名來限定嫉鲸。
在沒有虛函數(shù)的情況下,如果某個派生類的多個基類擁有同名的成員歹啼,同時玄渗,派生類又新增這樣的同名成員,在這種情況下狸眼,派生類成員將隱藏所有基類同名成員藤树。這時使用“對象名.成員名”方式可以唯一標識和訪問派生類新增成員,基類同名成員也可以拓萌。
但是如果派生類在多繼承的時候岁钓,沒有聲明這樣新的同名成員。這時就必須通過使用基類名和作用域分辨符來標識成員微王。
示例:
#include <QCoreApplication>
#include <QDebug>
class B1 {
public:
int nV;
void fun(){qDebug()<<"Memberof B1"<<", nV = "<<nV;}
};
class B2 {
public:
int nV;
void fun(){qDebug()<<"Memberof B2"<<", nV = "<<nV;}
};
class C : public B1, public B2 {
public:
int nV;
void fun(){qDebug()<<"Memberof C"<<", nV = "<<nV;}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
C c1;
c1.nV = 1;
c1.fun();
c1.B1::nV = 2;
c1.B1::fun();
c1.fun();
c1.B2::nV = 3;
c1.B2::fun();
c1.fun();
return a.exec();
}
示例運行結(jié)果:
通過作用域分辨符屡限,就明確地唯一標識了派生類中由基類所繼承來的成員,達到訪問的目的炕倘,解決了成員被隱藏的問題钧大。
如果派生類沒有聲明新的與基類同名的成員。
例如罩旋,將上例中的派生類C啊央,改為如下形式:
class C : public B1, public B2 {
};
再次,運行會出現(xiàn)報錯:
我們注釋掉會導致出錯的代碼瘸恼,再次運行劣挫,輸出結(jié)果:
如果某個派生類的部分或者全部直接基類是從另一個共同的基類派生而來,在這些直接基類中东帅,從上一級基類繼承來的成員就擁有相同的名稱压固,因此派生類中也就會產(chǎn)生同名現(xiàn)象,對這種類型的同名成員也要使用作用域分辨符來唯一標識靠闭,而且必須用直接基類來進行界定帐我。
#include <QCoreApplication>
#include <QDebug>
class B0 {
public:
int nV = 0;
void fun(){qDebug()<<"Memberof B0 and nV = "<<nV;}
};
class B1:public B0 {
public:
int nV1;
};
class B2:public B0 {
public:
int nV2;
};
class C:public B1, public B2 {
public:
int nVd;
void fun(){qDebug()<<"Memberof C";}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
C c1;
c1.B1::nV = 2;
c1.B1::fun();
c1.B2::nV = 3;
c1.B2::fun();
c1.B1::fun();
return a.exec();
}
運行結(jié)果:
在例子中可以看出坎炼,在這種情況下,派生類的對象在內(nèi)存中就同時擁有成員nV及fun的兩份同名拷貝拦键。