C++
- 知识基础
- 流操作符
- 类 & 基础
- 初始化和重载
- 类 & 高级
- 继承和多态
- 模板 & 标准模板库STL
已经了解类的基础操作,通过设计好的成员可以实现比较好的抽象;这里我们进一步介绍类的一些其他操作,如静态成员、友元函数可以更加灵活的实现需求!
一、静态成员
每个对象都有属于自己的数据成员,同类的两个对象,他们的数据成员变量是独立的,有属于自己的存储空间。
C/C++的static
关键字可以声明静态变量,静态变量的生存周期为整个程序的始终,静态变量名在整个生存周期之中不能够重复,它被定义在进程的数据段(在《计算机组成原理》中可以学习到生存周期、段的概念),所有的函数共用这一个静态变量!
类的静态数据成员:在类的定义之中,数据成员说明在最前面加上static
关键字修饰;
- 同一个类中的所有对象共享该变量;
- 无论是否定义该类的对象,静态数据成员都存在,分配了存储空间;
- 类内说明!类外定义!
- 默认初始化为零值;
- 区别于一般的静态变量,类的静态数据成员只能由类的对象使用,我们也可以通过类的访问修饰符控制对象对静态数据成员的访问。
class Test{
public:
static int s;//类内说明
}
int Test::s;//类外定义,默认初始化为 0
int main(){
Test a, b;
a.s++;
b.s++;
cout<<b.s<<endl;//输出值为 2
return 0;
}
类的静态函数成员:类中的一个函数,最前面有static
修饰符;
- 静态函数成员只能访问类中的非静态成员!
- 它本质上时独立于对象的,非静态成员在定义对象之前是不存在的,所以只能调用生存周期和他一样的静态成员;
- 基于静态函数成员的特性可以给对象设置特殊任务—
- 静态函数成员没有
this
指针,因为他是被类所有的,所有对象共有。
class Test{
private:
static int s;//类内说明
public:
static void fun(int i){a = i}//也可以定义在类外部
}
int Test::s;//类外定义,默认初始化为 0
int main(){
Test::fun(7);//没有定义对象直接调用,指明所属类即可!!!
Test a, b;
a.s++;
b.s++;
cout<<b.s<<endl;//输出值为 9
a.fun(1);
cout<<a.s<<endl;//输出值为 1
return 0;
}
二、友元函数
友元函数不是类的成员函数,但是他可以访问类中定义的私有成员;
类的私有成员对于类外语句(包括其他类的语句、函数语句、对象调用等都是类外)是隐藏的,想要访问必须通过公开函数接口;一方面这样提高了安全性,但一方面又限制了我们的使用,尤其对一些函数或者一些类之间需要使用私有成员,但是又没有公共的接口时,我们可以定义友元函数!
友元函数既可以是一个外部函数,也可以是另外一个类的函数成员
它本质上时一个声明,在类的定义中声明 我朋友 是那一个函数,这样就可以允许该函数使用私有成员,格式:
friend <return type><function name>(<parameter list>);
在重载部分我们讲到流操作符重载需要使用友元函数实现,>> 和 << 涉及到自定义的类 和 系统定义好的标准输入输出对象cin和cout
重载流操作符
重载之后我们可以直接使用<<和>>对自定义类的对象进行输入输出,cout和cin分别是ostream和istream类的对象,我们需要在自定义的类中定义重载函数,并且以友元函数的形式实现!
- operator<< 是全局函数不需要指明所属的类。。。
- operator>> 是全局函数不需要指明所属的类。。。
//我们定义了ostream类的一个<<函数重载,但单纯的定义并不能访问自定义类私有成员
ostream & operator<<(ostream & strm, Test & obj){
strm<<obj.数据成员
return strm;//返回值是哦strm
}
class Test{
private:
数据成员
public:
friend ostream & operator<<(ostream & , Test &);
}
有如下调用
Test a, b;
cout<<a<<b<<endl;
cout对象首先处理<<a
,调用定义的重载函数,重载函数是可以访问自定义的类的私有数据成员,顺利返回的是一个ostream对象给cout,继续处理<<b
。
三、对象操作
对象数组
对象组合
就类比基本数据类型来看就行
总结
类 设计中的一些特殊操作方式,进一步提高自定义类的灵活性。。。对对象的使用。。。