学堂在线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