码迷,mamicode.com
首页 > 编程语言 > 详细

C++ Primer 学习笔记_17_类与数据抽象(3)_类作用域

时间:2015-07-25 20:03:02      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:c++   c++ primer   类与数据抽象   

C++ Primer 学习笔记_17_类与数据抽象(3)_类作用域

引言:

每个类都定义了自己的新作用域与唯一的类型。即使两个类具有完全相同的成员列表,它们也是不同的类型。每个类的成员不同与任何其他类(或任何其他作用域)的成员

 

一、类作用域中的名字查找

    1)首先,在使用该名字的块中查找名字的声明。只考虑在该项使用之前声明的名字。

    2)如果在1)中找不到,则在包围的作用域中查找。

如果找不到任何声明,则出错。

 

类的定义实际上是在两个阶段中处理:

   1)首先,编译器声明;

   2)只有在所有成员出现之后,才编译他们的定义本身。

 

类作用域中说明的标识符只在类中可见。除了类作用域,还有块作用域、文件作用域、函数原型作用域、函数作用域,举个例子:

#include<iostream>
using namespacestd;
 
class Test
{
public:
    int num;
};
 
//num = 20;        Error,num的作用域在类内部
int num =20;      // num的作用域是文件作用域,与类中的num是不同的作用域
 
int add(int a,int b);  // a, b两个标识符的作用域为函数原型作用域
 
int main(void)
{
    int num = 30;      // num为块作域
    {
        int num = 100; // num为块作域
    }
 
    cout << num << endl;
    cout <<::num << endl;
    return 0;
}
 
int add(int a,int b)   // 形参a与b也算是块作用域
{
    return a + b;
}


int test()
{
LABEL1: //函数作用域
    cout << "label1" <<endl;
    goto LABEL3;
LABEL2:
    cout << "label2" <<endl;
    goto LABEL1;
LABEL3:
    cout << "label3" <<endl;
    goto LABEL2;
}


1、类成员声明的名字查找

必须是在类中先定义类型名字,才能将它们用作数据成员的类型,或者成员函数的返回类型或形参类型。一旦一个名字被用作类型名,则该名字就不能被重复定义:

typedef double Money;
class Account
{
public:
   Money balance()
    {
       return bal;
    }
 
private:
   typedef long double Money; //Error
   Money bal;
};

2、类成员定于中的名字查找

    1)首先检查成员函数局部作用域中的声明

    2)如果在成员函数中找不到该名字的声明,则检查对所有类成员的声明

    3)如果在类中找不到该名字的声明,则检查在此成员函数定义之前的作用域中出现的声明。

 

3、类成员遵循常规的块作用域名字查找

   在程序中尽量不要使用相同名字的形参和成员

int height;
class Screen
{
public:
   typedef int index;
 
   //由于在函数形参中定义了height,
   //所以此处的height形参会屏蔽名为height的成员
   void dummy_fcn(index height)
    {
       cursor = width * height;
    }
 
private:
   index cursor;
   index height,width;
};

尽管类的成员被屏蔽了,但是仍然可以通过使用类名来限定成员名或显式使用this指针来使用:

    void dummy_fcn(index height)
    {
        cursor = width * this -> height;
        //这两条语句作用相同
        cursor = width * Screen::height;
    }

4、函数作用域之后,在类作用域中查找

  如果想要使用height成员,最好的方式还是为形参定义一个不同的名字:

    void dummy_fcn(index ht)
    {
        cursor = width * height;
    }

尽管height是先在dummy_fcn中使用,然后再声明,但是编译器还是确定这里用的是名为height的数据成员。

 

5、类作用域之后,在外围作用域中查找

   尽管全局对象height在类中被数据成员height屏蔽了,但还可以通过全局作用域确定操作符来限定名字,仍然可使用它:

   void dummy_fcn(index height)
    {
       cursor = width * ::height
    }

6、嵌套类、局部类

(1)、嵌套类

外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现。

从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类之外的作用域使用该类名时,需要加名字限定。

嵌套类中的成员函数可以在它的类体外定义。

嵌套类的成员函数对外围类的私有成员没有访问权,反之亦然。

嵌套类仅仅只是语法上的嵌入


(2)、局部类

类也可以定义在函数体内,这样的类被称为局部类(localclass)。局部类只在定义它的局部域内可见。

局部类的成员函数必须被定义在类体中。

局部类中不能有静态成员,关于类中的静态成员和静态成员函数以后再谈。

#include <iostream>
using namespace std;
 
class Outer
{
public:
   class Inner
    {
   public:
       void Fun();
       //{
       //  cout<<"Inner::Fun..."<<endl;
       //}
   };
public:
   Inner obj;
   void Fun()
    {
       cout << "Outer::Fun ..." << endl;
       obj.Fun();
    }
};
 
void Outer::Inner::Fun()
{
   cout << "Inner::Fun ..." << endl;
}
 
void Fun()
{
   class LocalClass
    {
   public:
       int num_;
       void Init(int num)
       {
           num_ = num;
       }
       void Display()
       {
           cout << "num=" << num_ << endl;
        }
 
       //static int num2_; // 局部类内部不能定义静态成员
   };
 
   LocalClass lc;
   lc.Init(10);
   lc.Display();
}
 
int main(void)
{
   Outer o;
   o.Fun();
 
   Outer::Inner i;
   i.Fun();
 
   Fun();
   //LocalClass lc;        Error,局部类只能在定义它的函数体中使用
   return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

C++ Primer 学习笔记_17_类与数据抽象(3)_类作用域

标签:c++   c++ primer   类与数据抽象   

原文地址:http://blog.csdn.net/keyyuanxin/article/details/47058677

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!