C++学习(第五章)
1.主要内容
数据的共享与保护
1.理解作用域,可见性,生存期。
2.理解静态和有元的概念。
3.const的用法用处。
1.作用域,可见性,生存期
作用域:一个标识符在程序正文中有效的部分。分为四大类:
a.原型作用域
只存在于函数声明阶段,这就是为什么函数声明的时候可以只写类型不写变量名(重载函数)
如double area(double radius)
b.局部作用域(块作用域)
函数的形参,在函数体的大括号之内。如:
void fun(inta)-------------------------**a的作用域**
{
int b=a;----------------------------b的作用域
cin>>b;
if(b>0)
{
int c;---------------------------c的作用域
....-----------------------------c的作用域
}----------------------------------b的作用域
}-------------------------------------a的作用域
具有局部作用域的变量称为局部变量。
c.类作用域
包括类体和类外成员函数体,所以在类外定义非构造函数的成员函数的时候可以直接调用类内公有成员数据。
d.命名空间作用域
最大的,作用范围最广的,用namespace 标识符名
来表示。
具有命名空间作用域的变量称为全局变量。
可见性:
即标识符的有效范围,如果标识符在外层中声明,且内层无相同标识符,则该标识符在内层可见;对于嵌套标识符,如果内层与外层同名,则内层不可见。
提示:可见性和作用域不仅适用于变量名,也适用于其他标识符。
生存期:
1)静态生存期:生存期与文件运行期相同,在文件域中的对象具有这种生存期。子函数局部变量冠以关键字static则在整个程序运行期都生存,但是局部可见,即如果主函数中有同名的变量,主函数不可以操作子函数中的静态变量
2)动态生存期:开始于定义点,结束语作用域,一般为块作用域中声明
类的静态数据成员
例子:具有静态数据成员-点个数-的Point类,需要统计总的Point个数,但是每个Point对象不应该包含这个个数
#include<iostream>
using namespace std;
class Point {
public:
Point(int x, int y) :x(x), y(y) { //构造函数使用初始列表初始化x,y
count++;
}
Point(const Point &p) { //复制构造函数
x = p.x; y = p.y; count++;
}
~Point() { count--; } //析构函数中点数减一
int getX() { return x; }
int getY() { return y; }
void showCount() {
cout << "Point count:" << count << endl;
}
private:
int x, y;
static int count;
};
int Point::count = 0; //类外初始化静态变量
int main()
{
Point a(4,5);
cout << "Point A" << a.getX()<<","<< a.getY()<<endl;
a.showCount();
Point b(a);
cout << "Point A" << b.getX() <<" ," << b.getY() << endl;
b.showCount();
return 0;
}
类的静态函数成员:用于处理静态变量,在被调用时要用
类.变量名
类的非静态函数成员则直接调用。
在上例代码中showCount函数前在static限定,则可以在没有定义任何对象的时候调用showCount函数:
Point::showCount();
静态成员函数由于没有this指针,所以不能访问本类中的非静态成员。引用静态成员函数有2种方式,一种是直接使用类来引用,如Constants::getPI();另一种是使用对象来引用,如constants.getPI()。(constants是类)
类的友元:
在类内使用friend关键字说明某个函数,则该函数可以调用类的私有变量(尽量不使用)
在公有继承方式下,派生类对象可以访问派生类中的保护成员和公有成员,也可以访问基类中的公有成员,但不能访问基类的保护成员。运算表达式要求数据类型相同。如:
class Base
{
protected; int amount;
public; Base(int n=0): amount(n){ }
int getAmount()const { retum amount; }
};
class Derived: public Base
{
protected: int value;
public: Derived(int m, int n): value(m). Base(n){ }
int getData()const{ return value+amount; }
};
可以用x.getData( )-x.getAmount( )
类与类之间的友元关系不可以继承,友元可以提高程序的运行效率(但破坏封装性),一个类的友元类中的成员函数都是这个类的友元函数。
const的用法:
1)const常用于函数输入引用形参修饰,使得形参引用的实参不被改变,相当于一个只读的,也多用于友元函数
2)在定义对象的时候,如果某个函数只是单纯的输出,不改变对象的状态,可以在该函数定义时加const限定,这样做可以方便调用常函数处理普通对象和常对象
共享数据的保护
1 常对象
常对象必须进行初始化,而且不能被更新。
不能通过常对象调用普通的成员函数
class A{};
const A a(3,4);//a是常对象,以后不能被更新
const int n=10;//正确,用10对常量n进行初始化
n=20;//错误,不能对常对象赋值。
2 常成员函数
const 是函数类型的一个组成部分,因此在函数定义部分也要带const关键字
常对象智能调用它的常成员函数,而不能调用其他成员函数。
无论是否通过常对象调用函数,在常成员函数调用期间,目的对象都被视为常对象,因此常成员函数不能更新目的对象的数据成员,也不能针对目的对象调用该类中没有用const修饰的成员函数。
const可以用于函数重载,通过非const的对象调用该函数,两个重载的函数都可以与之匹配,这时编译器将选择最近的重载函数。
void print();
void print() const;
注意:常成员函数可以引用const数据成员,但不能应用没有加const的数据成员;而const数据成员可以被const成员函数引用,也可以被非const成员函数引用。
#include<iostream>
using namespace std;
class VAC
public:
int f()constreturn 3;
int f()return 5;
;
int main()
VAC v1;
const VAC v2;
cout<<v1.f()<<v2.f();
return 0;
上面代码中,输出结果为53,常变量只能调用常成员函数,而其他变量则都可以,但调用常成员函数会优先级低。
常数据成员
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){} //常数据成员只能通过初始化列表,来获取初值,不可以在{}初始化
常引用
常引用所引用的对象不能被更新。