作用域
从小到大:
函数原型作用域:作用域是形参表中;
(块)局部作用域:初始化的函数体{}之内;
类作用域:类中可用,类外public可访问类名.对象名。静态成员的引用访问&非静态成员的指针访问;
文件作用域/静态作用域:起始于声明点,整个文件有效。
可见性
内层域向外层域,可见才能引用。
内外层标识符如果重名了,就会导致外层在内层中不可见。如上段程序输出 1 5,因为同名的局部作用域在第一个cout时被覆盖不可见。
int i;//文件
int main(){
i=5;//为全局变量赋值
{
int i=1;//局部
cout<<i<<endl;
}
cout<<i<<endl;
return 0;
}
生存期与类的静态
静态生存期:可在声明时加上static,生存期与程序运行期一致,全局变量天生具有静态生存期;
动态生存期:起始于声明,结束在作用域结束。
整个类的共有,但不是类内,用static。静态数据成员的声明是类内,而定义与初始化在类外——数据类型 类名::对象名的初始化;
例5.5静态对象成员
#include<iostream>
using namespace std;
class Point {
private:
int x, y;
static int count;
public:
void getpoint() { cout << "(" << x << "," << y << ")"<<endl; }
void showcount() { cout << count << endl; }
Point(int a, int b);//构造函数声明
Point(Point& p) { x = p.x; y = p.y; count++;}//复制构造函数
~Point() { count--; }//析构,数量下降(反构造)
};//class{}后要加分号
//构造函数
Point::Point(int a, int b) {
x = a;
y = b;
count++;
}
int Point::count = 0;//用类名来限定,初始化静态数据成员
int main() {
Point A(4, 5);
A.getpoint();
A.showcount();
Point b(A);
b.getpoint();
b.showcount();
return 0;
}
缺陷:但是当没有点时,这时不会出count=0。
例5.6静态函数成员
#include <iostream>
using namespace std;
class Point {
public:
Point(int x = 0, int y = 0) : x(x), y(y) { count++; }//构造函数
Point(Point &p) { //复制构造函数,&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 << endl;
}
private:
int x, y;
static int count; //静态数据成员声明,用于记录点的个数
};
int Point::count = 0;//静态数据成员定义和初始化,使用类名限定
int main() {
Point a(4, 5); //定义对象a,其构造函数回使count增1
cout << "Point A: " << a.getX() << ", " << a.getY();
Point::showCount(); //输出对象个数
Point b(a); //定义对象b,其构造函数回使count增1
cout << "Point B: " << b.getX() << ", " << b.getY();
Point::showCount(); //输出对象个数
return 0;
}
比起5.5,
1.由于函数改成静态函数,类中原本与静态数据成员有关的函数写成了 static void showCount() { }。
2.且主函数输出由对象名.函数写成了类名.函数,这个类的这个函数已经固定。
友元friend
可访问类的私有成元,增加灵活性,但是存在违背完整性,是封装与隐藏的机制。少使用。
友元函数:访问中必须有对象名。
class中函数加friend声明。
用对象做参数时,使用引用可以提高效率。&p但是引用是双向传递,可能会反向修改。
友元类:一个类的友元类中的成员函数都是这个类的友元函数
class A{
friend class B;//S对B开放权限,B中可以对A修改了
public:
private:
};
但是类的友元关系是单向的,上述的A并不能修改B。B是A的友元,但是A类不是B类的友元。
共享数据的保护
常对象const定义时就要初始化。
class A{};
A const a(4,5);//const写在数据类型说明符后
常引用:被引用的对象不能被更新,不想双向传递。只读。高效。如const Point &p
常数组ch6
常指针ch6
常函数:处理常对象。不更新对象
int prr(int a,Point b)const;
不打算改变对象状态的函数都可以加上const做出承诺。之后如果加上了常对象,会更加方便。
例5.7-5.9自己写一遍
//5-7
#include<iostream>
using namespace std;
class Pom {
private:
int a, b;
public:
void show(class Pom) { cout << a << " " << b << endl; }
void print(class Pom)const { cout << a << " " << b << endl; }
Pom(int a, int b) :a(a), b(b) {}
};
/*
Pom::Pom(Pom & x) {
a = x.a;
b = x.b;
}
*/
int main() {
int a, b;
Pom xx(6,8);
xx.print(xx);
xx.show(xx);
return 0;
}
静态常数据成员
//5.8
#include<iostream>
using namespace std;
class Pom {
private:
int a, b;
static const int c;//类内声明,const在前啊,且作为静态数据static
public:
void show(class Pom) { cout << a << " " << b << " " << c<< endl; }
void print(class Pom)const { cout << a << " " << b << " " << c << endl; }
Pom(int a, int b) ;
};
const int Pom::c = 10;//类外定义与初始化
Pom::Pom(int a, int b) :a(a), b(b) {};
int main(){
Pom aa(44, 6);
aa.show(aa);
aa.print(aa);
return 0;
}
常引用:高效的同时保持了实参的安全性
Point dist(const Point &p){
}
**static_cast<类型>**是一个c++运算符,功能是把一个表达式转换为某种类型,但没有运行时类型检查来保证转换的安全性。
构造函数与复制构造函数的语法还是要多写
多文件&编译预处理
类声明与定义 .h
类实现函数 .cpp
类的使用文件(main所在) .cpp
2.
“ .h"先从当前文件夹查找;
< >先从自带函数库查找。
3.标准库:
输入输出类
容器类与抽象数据类型
存储管理类
算法
错误处理
运行环境支持
4.
define/ifdef/else/ifndef/endif
实验五
用编译预处理
#ifndef CLIENT_H_
#define CLIENT_H_
....
#endif
静态数据成员的引用,需要**类名:😗*来修饰。
#include<iostream>
//#include"client.h"
using namespace std;
class client {
public:
static void change(char name);
client(char t);
static int getnumber();
client(const client& a);
private:
static char servername;
static int servernumber;
};
void client::change(char name) {
client::servername = name;
//client::servernumber++;
}
client::client(char t) { client::servername = t; client::servernumber++; }
client::client(const client& a) {
client::servername = a.servername;
client::servernumber++;
}
int client::getnumber() {
cout << client::servernumber << endl;
//return client::servernumber;
return 0;
}
int client::servernumber = 0;
char client::servername = 'a';
int main(){
char m = 'm';
client x(m);
x.change('n');
x.getnumber();
client y(m);
y.change('s');
y.getnumber();
return 0;
}
注:
如果拆分成多文件项目的话,如类声明.h+类定义.cpp+main.cpp,要将文件加进右侧解决方案资源管理器的项目解决方案源文件中,否则会报错:存在无法解析的外部符号错误。