数据的共享与保护
1.可见性
可见性上从对标识符的引用角度来谈的概念,表示从内层作用域向外层作用域看时能看见什么。如果某个标识符在外层中声明,且在内层中未声明,则该标识符在内层中可见;如果在内层中声明了一个与之相同的标识符,则外层中的标识符中内层不可见。
#include<iostream>
using namespace std;
int main(){
int i=5;
{
int i = 7;
cout<<i<<endl;//输出为7
}
cout<<i<<endl;//输出为5
}
2.变量的生存期
·静态生存期
从变量声明开始一直存在至程序结束,如函数中用static声明的变量。(注意静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。)
#include<iostream>
using namespace std;
void test(){
static int i=1;
i++;
cout<<i<<endl;
}
int main(){
test();
test();
test();//三次 调用test函数观察输出的i值
return 0;
}
·动态生存期
块作用域中声明的没有用static修饰的变量具有动态生存期。开始于声明处,终于该标识符的作用域结束处。
#include<iostream>
using namespace std;
int main(){
{
int i=1;
cout<<i<<endl;
}//i的生存期结束
cout<<i<<endl;//此处报错
return 0;
}
3.类的静态成员
1. C++中可以定义静态成员变量和静态成员函数
2. 静态成员属于整个类所有,不需要依赖任何对象。
3. 可以通过类名直接访问public 静态成员
4. 可以通过对象名访问public静态成员
静态成员函数可以直接访问静态成员静态成员不是对象的一部分,而是类的一部分,这是静态成员和普通成员之间最本质的区别。
1.静态成员变量的使用
#include<iostream>
using namespace std;
class Point {
public:
Point(int x = 0, int y = 0) :x(x), y(y) {//构造函数
count++;
}
Point(Point& p) { //复制构造函数
x = p.x;
y = p.y;
count++;
}
~Point() { count--; }
int getX() { return x; }
int getY() { return y; }
void showcount() {
cout << "object count:" << count;
}
private:
int x;
int y;
static int count;//静态成员变量
};
int Point::count = 0;
int main() {
Point a(4, 5);
cout << "Point a:" << a.getX() << " " << a.getY() << endl;
a.showcount();
cout << endl;
Point b(a);
cout << "Point b:" << a.getX() << " " << a.getY() << endl;
b.showcount();
return 0;
}
2.静态成员函数的使用
#include<iostream>
using namespace std;
class Point {
public:
Point(int x = 0, int y = 0) :x(x), y(y) {//构造函数
count++;
}
Point(Point& p) { //复制构造函数
x = p.x;
y = p.y;
count++;
}
~Point() { count--; }
int getX() { return x; }
int getY() { return y; }
static void showcount() { //静态成员函数
cout << "object count:"<<count;
}
private:
int x;
int y;
static int count;
};
int Point::count = 0;
int main() {
Point a(4, 5);
cout <<"Point a:"<< a.getX ()<< " " << a.getY()<<endl;
Point::showcount();
cout << endl;
Point b(a);
cout << "Point b:" << a.getX() << " " << a.getY() << endl;
Point::showcount();
return 0;
}
4.类的友元
有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的。例如被重载的操作符,如输入或输出操作符,经常需要访问类的私有数据成员。
1.友元函数
友元(frend)机制允许一个类将对其非公有成员的访问权授予指定的函数或者类,友元的声明以friend开始,它只能出现在类定义的内部,友元声明可以出现在类中的任何地方:友元不是授予友元关系的那个类的成员,所以它们不受其声明出现部分的访问控制影响。通常,将友元声明成组地放在类定义的开始或结尾是个好主意。
友元函数是指某些虽然不是类成员函数却能够访问类的所有成员的函数。类授予它的友元特别的访问权,这样该友元函数就能访问到类中的所有成员。
#include <iostream>
using namespace std;
class A
{
public:
friend void set_show(int x, A &a); //该函数是友元函数的声明
private:
int data;
};
void set_show(int x, A &a) //友元函数定义,为了访问类A中的成员
{
a.data = x;
cout << a.data << endl;
}
int main(void)
{
class A a;
set_show(1, a);
return 0;
}
2.友元类
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。
关于友元类的注意事项:
(1) 友元关系不能被继承。
(2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
(3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。
#include <iostream>
using namespace std;
class A
{
public:
friend class C; //这是友元类的声明
private:
int data;
};
class C //友元类定义,为了访问类A中的成员
{
public:
void set_show(int x, A &a) { a.data = x; cout<<a.data<<endl;}
};
int main(void)
{
class A a;
class C c;
c.set_show(1, a);
return 0;
}