目录
一、标识符的作用域与可见性
作用域
作用域是一个标识符在程序正文中有效的区域
分类
·函数原型作用域
·局部作用域(块作用域)
·类作用域
·文件作用域
·命名空间作用域
1)函数原形作用域
·函数原型中的参数,其作用域始于"(",止于")"
double area(double radius);
2)局部作用域
·函数的形参、在块中声明的标识符的作用域,自声明处起,限于块中
void fun(int a) { //a的范围在整个函数
int b = a; //b的范围仅限fun函数体
cin >> b;
if (b > 0) {
int c; //c的范围仅限if语句
......
}
}
3)类作用域
·类的成员具有类作用域,其范围包括类体和非内联成员函数的函数体
·如果在类作用域以外访问类的成员,要通过类名(访问静态成员),或者该类的对象名、对象引用、对象指针(访问非静态成员)
4)文件作用域
·不在前述各个作用域中出现的声明,就具有文件作用域,这样声明的标识符其作用域开始于声明点,结束于文件尾
5)命名空间作用域
可见性
可见性是从对标识符的引用的角度来谈的概念,表示从内层作用域向外层作用域“看”时能看见什么
·如果标识在某处可见,就可以在该处引用此标识符
·如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则该标识符在内层可见
·对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标识符,则外层作用域的标识符在内层不可见(被屏蔽)
举例:
#include<iostream>
using namespace std;
int i; //全局变量,文件作用域
int main() {
i = 5; //为全局变量i赋值
{
int i; //局部变量,局部作用域
i = 7;
cout << "i = " << i << endl; //输出7
}
cout << "i = " << i << endl; //输出5
return 0;
}
二、对象的生存期
静态生存期
·与程序的运行期相同
·在文件作用域中声明的对象具有这种生存期
·在函数内部声明静态生存期对象,要冠以关键字static
动态生存期
·始于程序执行到声明处,止于命名该标识符的作用域结束处
·块作用域中声明的,没有用static修饰的对象是动态生存期的对象(习惯称局部生存期对象)
举例:
#include<iostream>
using namespace std;
int i = 1; // i 为全局变量,具有静态生存期
void other() {
static int a = 2;
static int b; //a,b为静态局部变量,具有全局寿命,局部可见, 只在第一次进入函数时被初始化
int c = 10; //c为局部变量,具有动态生存期,每次进入函数时都初始化
a += 2; i += 32; c += 5;
cout << "---OTHER---\n";
cout << " i: " << i << " a: " << a << " b: " << b << " c: " << c << endl;
b = a;
}
int main() {
static int a; //静态局部变量,有全局寿命,局部可见
int b = -10; //b, c为局部变量,具有动态生存期
int c = 0;
cout << "---MAIN---\n";
cout << " i: " << i << " a: " << a << " b: " << b << " c: " << c << endl;
c += 8; other();
cout << "---MAIN---\n";
cout << " i: " << i << " a: " << a << " b: " << b << " c: " << c << endl;
i += 10; other();
return 0;
}
三、类的友元
友元是C++提供的一种破坏数据封装和数据隐藏的机制
·类的友元关系是单向的。如果声明B类是A类的友元,B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有和保护数据
·为确保数据的完整性,及数据封装与隐藏的原则,建议尽量不使用或少使用友元
友元函数
·友元函数是在类声明中由关键字friend修饰说明的非成员函数,在其函数体中能够通过对象名访问 private 和 protected 成员
·作用:增加灵活性,使程序员可以在封装和快速性方面做合理选择
注:访问对象中的成员必须通过对象名
举例:
//此例亦为常引用举例
#include <iostream>
#include <cmath>
using namespace std;
class Point { //Point类声明
public:
Point(int x = 0, int y = 0) : x(x), y(y) { }
int getX() { return x; }
int getY() { return y; }
friend float dist(Point &a, Point &b);
private:
int x, y;
};
float dist(const Point& a, const Point& b) { //将引用设置为常引用不会意外地发生对实参的更改
double x = a.x - b.x;
double y = a.y - b.y;
return static_cast<float>(sqrt(x * x + y * y));
}
int main() {
Point p1(1, 1), p2(4, 5);
cout << "The distance is: ";
cout << dist(p1, p2) << endl;
return 0;
}
友元类
·若一个类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员
·语法形式
将友元类名在另一个类中使用friend修饰说明
class A {
friend class B; //类B是类A的友元
public:
void display() {
cout << x << endl;
}
private:
int x;
};
class B {
public:
void set(int i);
void display();
private:
A a; //类B可以访问类A的任意成员
};
//接口与实现分离
void B::set(int i) {
a.x = i;
}
void B::display() {
a.display();
};
四、共享数据的保护
对于既需要共享、又需要防止改变的数据应该声明为常类型(用const进行修饰)
1)常对象
必须进行初始化, 不能被更新
//const 类名 对象名
class A {
public:
A(int i, int j) { x = i; y = j; }
...
private:
int x, y;
};
A const a(3, 4); //a是常对象,不能被更新
2)常成员
常数据成员: const 数据成员
举例:
#include <iostream>
using namespace std;
class A {
public:
A(int i);
void print();
private:
const int a;
static const int b; //静态常数据成员
};
const int A::b = 10;
A::A(int i) : a(i) { }
void A::print() {
cout << a << ":" << b << endl;
}
int main() {
A a1(100), a2(0); //建立对象a1和a2,并以100和0作为初值,分别调用构造函数,通过构造函数的初始化列表给对象的常数据成员赋初值
a1.print();
a2.print();
return 0;
}
常成员函数: 返回值类型 函数名(参数表)const{ 函数体 } //const是函数类型的一个组成部分
·常成员函数不更新对象的数据成员
·通过常对象只能调用它的常成员函数
举例:
#include<iostream>
using namespace std;
class R {
public:
R(int r1, int r2) : r1(r1), r2(r2) { }
void print();
void print() const; //const也是区分重载函数的一个因素
private:
int r1, r2;
};
void R::print() {
cout << r1 << ":" << r2 << endl;
}
void R::print() const { //显式的标出const,编译器才会认真审查函数是否改变对象状态
cout << r1 << ";" << r2 << endl;
}
int main() {
R a(5, 4);
a.print(); //调用void print()
//若没有定义该函数,对象a也调用常函数。普通对象可以调用常函数
const R b(20, 52); //定义的常对象只能用常函数处理;不是常函数,不能通过常对象调用
b.print(); //调用void print() const
return 0;
}
3)常引用
·被引用的对象不能被更新
·语法形式 const 类型说明符 &引用名
举例见友元函数举例
4)常数组
·数组元素不能被更新
·语法形式 类型说明符 const 数组名[大小]
5)常指针
·指向常量的指针