cpp——类——作用域 名字查找

时间:2022-10-30 15:41:01

概述

在类外部看来,类类型跟非类类型,类类型对象跟非类类型对象在使用上无区别,类类型如内置类型一般使用,类类型对象如内置类型对象一般使用,但在类内部则存在复杂作用域,这就是类作用域,类作用域对类外部是透明的

对象名字查找

class CAnimal
{
public:
CAnimal() : mGroup(1) {}

public:
int mGroup;

public:
void init() { cout << "CAnimal::init()" << endl; }

public:
static int totalGroup;

public:
static int getTotalGroup() { cout << "CAnimal::getTotalGroup()" << endl; return totalGroup; }
};

int CAnimal::totalGroup = 5;

class CDog : public CAnimal
{
public:
CDog() : mGroup(2) {}

public:
int mGroup;

public:
void init() { cout << "CDog::init()" << endl; }

public:
static int totalGroup;

public:
static int getTotalGroup() { cout << "CDog::getTotalGroup()" << endl; return totalGroup; }
};

int CDog::totalGroup = 8;

class CHusky : public CDog
{
public:
CHusky() : mGroup(3) {}

public:
int mGroup;

public:
void init() { cout << "CHusky::init()" << endl; }

public:
static int totalGroup;

public:
static int getTotalGroup() { cout << "CHusky::getTotalGroup()" << endl; return totalGroup; }

public:
void search()
{
cout << "mGroup = " << mGroup << endl;
init();
cout << "totalGroup = " << totalGroup << endl;
getTotalGroup();
}
};

int CHusky::totalGroup = 58;
void search_obj_name(){    CHusky husky;    husky.search();}
output:
mGroup = 3
CHusky::init()
totalGroup = 58
CHusky::getTotalGroup()
删除CHusky除search外的所有成员
class CAnimal
{
public:
CAnimal() : mGroup(1) {}

public:
int mGroup;

public:
void init() { cout << "CAnimal::init()" << endl; }

public:
static int totalGroup;

public:
static int getTotalGroup() { cout << "CAnimal::getTotalGroup()" << endl; return totalGroup; }
};

int CAnimal::totalGroup = 5;

class CDog : public CAnimal
{
public:
CDog() : mGroup(2) {}

public:
int mGroup;

public:
void init() { cout << "CDog::init()" << endl; }

public:
static int totalGroup;

public:
static int getTotalGroup() { cout << "CDog::getTotalGroup()" << endl; return totalGroup; }
};

int CDog::totalGroup = 8;

class CHusky : public CDog
{
public:
void search()
{
cout << "mGroup = " << mGroup << endl;
init();
cout << "totalGroup = " << totalGroup << endl;
getTotalGroup();
}
};
void search_obj_name(){    CHusky husky;    husky.search();}
output:
mGroup = 2
CDog::init()
totalGroup = 8
CDog::getTotalGroup()
把CDog除构造函数外的所有成员访问权限改为private
class CAnimal
{
public:
CAnimal() : mGroup(1) {}

public:
int mGroup;

public:
void init() { cout << "CAnimal::init()" << endl; }

public:
static int totalGroup;

public:
static int getTotalGroup() { cout << "CAnimal::getTotalGroup()" << endl; return totalGroup; }
};

int CAnimal::totalGroup = 5;

class CDog : public CAnimal
{
public:
CDog() : mGroup(2) {}

private:
int mGroup;

private:
void init() { cout << "CDog::init()" << endl; }

private:
static int totalGroup;

private:
static int getTotalGroup() { cout << "CDog::getTotalGroup()" << endl; return totalGroup; }
};

int CDog::totalGroup = 8;

class CHusky : public CDog
{
public:
void search()
{
//cout << "mGroup = " << mGroup << endl;
//init();
//cout << "totalGroup = " << totalGroup << endl;
//getTotalGroup();
}
};
void search_obj_name(){    CHusky husky;    husky.search();}
注:编译error,不能访问private member

总结

在c中,对象声明search从对象名字所在当前作用域当前位置开始,向外层作用域forward search,一旦找到相应名字对象声明,search terminate,因此内层对象声明会屏蔽外层对象声明,局部作用域对象声明会屏蔽全局作用域对象声明 在c++类中,对象声明search分三步走:
  • 对象声明search从对象名字所在当前作用域(成员函数作用域内)当前位置开始search,向外层作用域forward search,一旦找到相应名字对象声明,search terminate,因此内层对象声明会屏蔽外层对象声明,在这一步中遵循c的函数内对象名字声明search规则
  • 如果在成员函数作用域内search不到相应名字对象声明,接着在类作用域内search,沿着继承体系上溯search,一旦找到相应名字对象在类作用域内的定义,search terminate,search过程中对象类型ignored,对象访问权限ignored,因此子类成员对象名字定义会屏蔽父类成员对象名字定义
  • 如果在类继承体系内找不到相应名字对象定义,接着在类作用域外(即全局作用域内)search相应名字对象声明,一旦找到相应名字对象声明,search terminate,如果在全局作用域内仍search不到目标对象名字声明,编译error
同一类作用域内的所有成员(non-static数据成员,non-static函数成员,static数据成员,static函数成员)本质位于同一作用域,而对象名字定义search ignored对象名字的类型,因此同一类作用域内的所有成员名字不能重复(成员名字都是定义) c++类内的对象声明search比c多了第二步,即类作用域内的相应名字对象定义search,从c角度理解,类继承体系本质就是类作用域嵌套,子类作用域和父类作用域形成嵌套作用域,子类作用域位于内层作用域,父类作用域位于外层作用域,因此类作用域内的相应名字对象定义search从对象名字所在当前类作用域(内层作用域)开始,沿着继承体系上溯search(向外层作用域forward search),因此子类成员对象名字定义会屏蔽父类成员对象名字定义,嵌套的类作用域最外层,即类继承体系的root类作用域,最终位于全局作用域内,因此如果类继承体系中search不到对应的对象名字定义,最后会在全局作用域内search对象名字声明,如果在全局作用域内也search不到目标对象名字声明,编译error
CAnimal
{
... //all animal obj name list
CDog
{
... //all dog obj name list
CHusky
{
}
}
}
注:父类所有对象定义位于子类作用域之前,即子类作用域开始于父类作用域所有对象定义之后 从访问权限角度理解,当前类对自身类所有成员都有访问权限,而对于父类成员,只有public和protected成员才有访问权限,因此从业务逻辑考虑优先search当前类成员定义非常自然

类型名字查找

类作用域内也可定义类型,称为嵌套类型,类作用域内类型名字查找遵循对象名字查找相同原理和过程,不再赘述