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

本文详细阐述了C++中类作用域的概念及其工作原理,包括对象名字查找和类型名字查找的过程,解释了如何在不同作用域中解决名字冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

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

对象名字查找

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当前类成员定义非常自然

类型名字查找

类作用域内也可定义类型,称为嵌套类型,类作用域内类型名字查找遵循对象名字查找相同原理和过程,不再赘述
### 变量作用域与生命周期的概念 #### 定义 变量的作用域定义了该变量可以在哪些部分的代码中访问。不同的编程语言有不同的机制来决定变量的作用域,但在大多数情况下,可以分为全局作用域、局部作用域以及块级作用域。 - **全局作用域**:在整个程序范围内都可以访问这些变量[^1]。 - **局部作用域**:仅限于特定函数内部使用的变量,在此函数外部无法直接访问它们。 - **块级作用域**:当涉及到更细粒度控制时,某些语言允许通过大括号 `{}` 或者其他方式定义一个新层次的作用域;这种情况下创建出来的就是所谓的“块级”作用域内的变量。 对于 Python 来说,还存在一种特殊的查找顺序用于解析未限定名称的空间,即按照 LEGB 规则(Local, Enclosing, Global 和 Built-in),依次检查本地命名空间、封闭函数中的任何嵌套作用域、文件级别的全局命名空间最后才是内置命名空间[^3]。 #### 生命周期 另一方面,“生命周期”指的是对象自诞生至消亡所经历的过程。具体来说: - 对于 C++ 中声明为 `static` 的静态局部变量而言,虽然其可见性仍然局限于单个函数体内,但是它的生存期却贯穿整个应用程序运行期间,并且只会在第一次调用相应位置处执行初始化操作[^4]。 - 非静态类型的局部实体通常是在每次进入对应过程体之后才建立起来并分配内存资源给它自己使用直到退出为止才会释放掉这部分存储单元。 因此可以看出,两者之间存在着紧密联系却又互不相同之处——前者决定了某个名字能在多大的范围内有效识别出来而后者则是关于实际数据结构存在于计算机系统里的持续时间长短问题。 ```cpp // 示例展示C++中不同类型的变量及其生命周期差异 #include <iostream> using namespace std; void func() { int local_var = 0; // 局部自动变量,每次调用func都会重新创建和销毁 static int stat_local = 0;// 静态局部变量,首次调用func时创建,后续保持不变直至程序结束 cout << "local_var: " << ++local_var << endl; cout << "stat_local: " << ++stat_local << endl; } int main(){ for(int i=0;i<5;++i){ func(); } } ``` ```python # Python例子说明普通局部变量vs带有闭包特性的自由变量之间的区别 def outer(): x = 'outer_x' # 外层函数中的局部变量 def inner(): nonlocal x # 使用nonlocal关键字改变外层变量x的行为模式 y = 'inner_y' print(x,y) return inner # 返回内层函数作为结果的一部分返回出去形成闭包环境 closure_example = outer() closure_example() # 调用闭包实例会打印出两个字符串值表示内外两重作用域下的同名标识符状态 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值