学堂在线C++程序设计第六章学习笔记

学堂在线C++程序设计第六章学习笔记

变量和对象定义在不同的位置

  • 其作用域,可见性,生存期都不同

友元:

  • 对一些类外的函数,其他的类,给预授权,使之可以访问类的私有成员

标识符的作用域与可见性

作用域分类:

  • 函数原型作用域
  • 局部作用域
  • 类作用域
  • 文件作用域
  • 命名空间作用域

函数原型作用域

  • 函数原型中的参数

类的作用域

  • 类的成员具有类作用域,其范围包括类体和成员函数体
  • 在类作用域以外访问类的成员
    • 静态成员:通过类名,或者该类的对象名,对象引用访问
    • 非静态成员:通过类名,或该类的对象名,对象引用,对象指针访问

文件作用域

  • 不在前述各个作用域中出现的声明,就具有文件作用域
  • 其作用域开始于声明点,结束于文件尾

可见性

  • 可见性是从对标识符的引用角度来谈论的
  • 可见性表示从内层作用域向外层作用域“看”时能看见什么
  • 如果标识在某处可见,就可以在该处引用此标识符
  • 如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则该标识符在内层可见
  • 对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标识符,则外层标识符在内层不可见

对象的生存期

静态生存期

  • 这种生存期与程序的运行期相同
  • 在文件作用域中声明的对象具有这种生存期
  • 在函数内部声明静态生存期对象,要冠以关键字static

动态生存期

  • 开始于程序执行到声明点时,结束于命名该标识符的作用域结束处
  • 块作用域中声明的,没有用static修饰的对象是动态生存期的对象(也称局部生存期对象)

静态数据成员

  • 用关键词static修饰
  • 为该类的所有对象共享,静态数据成员具有静态生存期
  • 必须在类外定义和初始化,用(::)来指明所属的类
class Point{
    public:
        static int count;  //声明
}
int Point::count = 0; //初始化

静态函数成员

静态函数成员主要用来处理静态数据成员

静态函数成员要处理非静态数据成员,需要用对象调用

类的友元

  • 友元是C++提供的一种破坏数据封装和数据隐藏的机制
  • 通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息
  • 可以声明友元函数和友元类
  • 为了确保数据的完整性,及数据封装与隐藏的原则,建议慎用友元

友元函数

  • 友元函数是在类声明中由关键字friend修饰说明的非成员函数,在它的函数体中能够通过对象名访问private和protected成员
  • 作用:增加灵活性,使程序员可以在封装和快速性方面做合理选择
  • 访问对象中的成员必须通过对象名

友元类

  • 若一个类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员
  • 声明语法:将友元类名在另一个类中使用friend修饰说明
class A{
    friend class B;
    public:
        void display() {
            cout << X << endl;
        }
    private:
        int X;
}

class B{
    public:
        void set(int i);
        void display();
    private:
        A a;
}

void B::set(int i) {
    a.X = i;
}

void display() {
    a.display();
}

类的友元关系是单向的:

  • 声明B类是A类的友元 不等于 A类是B类的友元

共享数据的保护

常类型

  • 常对象:必须进行初始化,不能被更新。
    const 类名 对象名
  • 常成员:
    用 const 进行修饰的类成员:常数据成员和常函数成员
  • 常引用:被引用的对象不能被更新
    const 类型说明符 &引用名;
  • 常数组:数组元素不能被更新
    类型说明符 const 数组名[大小]
  • 常指针:指向常量的指针

常成员:用const修饰的对象成员

  • 常成员函数
    • 使用const 关键字说明的函数
    • 常成员函数不更新对象的数据成员
    • 常成员函数说明格式:
      类型说明符 函数名(参数表)const;
      这里,const是函数类型的一个组成部分,因此在实现部分也要带const关键字
    • const 关键字可以被用于参与对重载函数的区分
    • 通过常对象只能调用它的常成员函数
  • 常数据成员
    • 使用 const 说明的数据成员

常引用

  • 在友元函数中用常引用做参数,既能获得较高的执行效率,又能保证实参的安全性

多文件结构和预编译处理命令

C++程序的一般组织结构

  • 一个工程可以划分为多个源文件
    • 类声明文件(.h文件)
    • 类实现文件(.cpp文件)
    • 类的使用文件(main()所在的.cpp文件)
  • 利用工程来组合各个文件

文件1 Point.h

class Point{
    //类的定义
    public:
        Point(int x =0,int y = 0):x(x),y(y){}
        Point(const Point &p);
        static void showCount();
    private:
        int x,y;
        static int count;
}

文件2 Point.cpp

#include "Point.h"
#include <iostream>
using namespace std;

int Point::cout = 0;

Point::Point(const Point &p):x(p.x),y(p.y){
    count++;
}

void Point::showCount() {
    cout << "Object count =" << count << endl;
}

文件3 主函数 main.cpp

#include "Point.h"
#include <iostream>
using namespace std;

int main() {
    Point a(4,5);
    cout << "Point A:" < a.getX() << "," << a.getY();
    Point::showCount();
    Point b(a);
    cout << "Point B:" << b.getX() << "," << b.getY();
    Point::showCount();
    return 0;
}

外部变量

  • 除了在定义它的源文件中可以使用外,还能被其他文件使用
  • 文件作用域中定义的变量,默认情况下都是外部变量
  • 在其它文件中如果需要使用,需要用extern关键字声明

外部函数

  • 在所有类之外声明的函数(也就是非成员函数),都是具有文件作用域的
  • 这样的函数都可以在不同的编译单元中被调用
  • 只要在调用之前进行引用性声明(即声明函数原型)即可

将变量和函数限制在编译单元内

  • 在匿名命名空间中定义的变量和函数,都不会暴露给其它的编译单元
namespace {
    //匿名的命名空间
    int n;
    void f() {
        n++;
    }
}

标准C++库

  • 标准C++类库是一个极为灵活并可扩展的可重用软件模块的集合

标准C++类与组件在逻辑上分为6种类型:

  • 输入/输出类
  • 容器类与抽象数据类型
  • 存储管理类
  • 算法
  • 错误处理
  • 运行环境支持

编译预处理

  • #include 包含指令
    • 将一个源文件嵌入到当前源文件中该点处
    • #include<文件名>
      • 按标准方式搜索,文件位于C++系统目录的include子目录下
    • #include “文件名”
      • 首先在当前目录中搜索,若没有,再按标准方式搜索
  • #define 宏定义指令
    • 定义符号常量,很多情况下已被const定义语句取代
    • 定义带参数宏,已被内联函数取代
  • #under
    • 删除由 #define 定义的宏,使之不再起作用

条件编译指令 #if 和 #endif
#if 常量表达式
//当 常量表达式 非零时编译
程序正文
#endif

条件编译指令 #else
#if 常量表达式
//当 常量表达式 非零时编译
程序正文1
#else
//当 常量表达式 为零时编译
程序正文2
#endif

条件编译指令 #elif
#if 常量表达式1
//当 常量表达式1 非零时编译
程序正文1
#elif 常量表达式2
//当 常量表达式2 非零时编译
程序正文2
#else
//其他情况下编译
程序正文3
#endif

条件编译指令
#ifdef 标识符
程序段1
#else
程序段2
#endif

  • 如果 标识符 经 #define 定义过,且未经undef删除,则编译程序段1
  • 否则编译程序段2

条件编译指令
#ifndef 标识符
程序段1
#else
程序段2
#endif

  • 如果标识符未被定义过,则编译程序段1
  • 否则编译程序段2
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值