标题:【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类

@水墨不写bug

(图片来源于网络)

目录

(一)静态成员

(二)友元

 (三)内部类

(四)深入理解类和对象、总结

正文开始: 

(一)静态成员

        C语言中有静态的概念,比如静态函数和静态变量。

静态变量:存储在静态区,随着主函数的开始而创建并初始化,随着程序结束而销毁。选择创建静态变量,会使变量的生命周期延长到程序结束。

静态函数则是不同的概念:静态函数只能在当前源文件中访问,不能被其他源文件访问调用。选择定义静态函数的作用是将函数的作用域限制在当前源文件内,并且可以避免与其他源文件中定义的同名函数发生冲突。

        Cpp中,由于新增了类和对象的特性,对静态变量的处理就有所不同了。

         类中是可以创建静态变量的,由于静态变量存储在静态区,只初始化一次,所以一个类(Class)内部(定义)包含有的静态变量是可以通过任意一个这个Class创建的对象来访问的,这也就表明了这个静态变量是属于这个类的,而不是单独属于某个实例化的对象。

        如果我们执行下面这一段代码:

#include

#include

using namespace std;

class A

{public:

private:

static int _a;

int _b;

int _c;

};

int main()

{

A aa;

cout << sizeof(aa) << endl;

return 0;

}

 结果可能会让你惊讶:静态对象_a不是存储在对象aa中的!

        1.静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。

(类的成员函数指针也不存放在类内,而是存放在公共的代码段)

 其次,类静态对象的定义是在类外部的。

class A

{

public:

private:

static int _a;

int _b;

int _c;

};

int A::_a = 5;

         2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明

         访问方式:

        类静态成员对象有两种访问方式:

        1)通过实例化的对象访问;

A aa;//实例化一个对象

aa._a++;//通过对象访问

        2)通过类名访问;

A::_a++;//直接通过类名访问

        3. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员

>同时就是说:静态成员函数只可以访问静态变量

 4. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

(二)友元

        友元是通过一个关键字(friend)来实现的;我们在实现一个类的时候,通常把成员函数定义为共有(public),而把成员变量定义为私有(private)。

        如果我们在项目中想要通过重载cout来输出自己的自定义类型对象时,一定会遇到这样的问题:

ostream& operator<<(const Date d)

{

out << this->_year << " " << this->_month << " " << this->_day;

out << endl;

return out;

}

        由于用类对象调用重载后的函数时,参数的顺序首先是this,其次是其他的对象。所以调用重载后的cout会十分的别扭,而与常规的逻辑不同:

cout<

         解决方法就是第一个参数必须是cout,其次是其他参数。由于类内部定义的函数的第一个参数必是this指针,所以这个逻辑正确的函数必须在类外定义。

        但是由于类外的函数不能访问类的private的成员函数,所以为了解决这一问题,Cpp就引入“友元”的概念:

        成为友元的函数可以突破private的限制,直接访问类的私有成员变量。

        友元分为:#友元函数和友元类#

 注意:

        1)友元提供了一种突破封装的方式,有时提供了便利;

        2)但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

        通过定义友元函数,我们可以写出逻辑正确的cout重载函数:

ostream& operator<<(ostream& out, const Date d)

{

out << d._year << " " << d._month << " " << d._day;

out << endl;

return out;

}

 函数的效果:

 (三)内部类

        什么是内部类?如果一个类,它定义在另一个类的内部,那么这个定义在内部的类就称为“内部类”。

示例:

class A

{

class B

{

int _c;

};

};

此时,B就是A的内部类。 

内部类也是一个类,只不过他被A的作用域又封装了一层,想要找到B,则要:

//创建一个类B,需要在A的作用域中去寻找

A::B aa;

 内部类是一个独立的类,它是外部类A的友元类:        

        内部类B可以访问A的私有成员,而A不能访问B的私有成员。

        (内部可以访问外部,而不能反着来)

 其他特性:         1. 内部类可以定义在外部类的public、protected、private都是可以的。         2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。         3. sizeof(外部类)=外部类,和内部类没有任何关系。

(四)深入理解类和对象、总结

        假如将来你要开一家外卖公司,需要打造你的项目,这时你该如何保存信息?

        创建多个类:外卖骑手,商家,顾客类;

每个类包含的信息(包含的成员变量),拥有的功能(实现的函数)都是最必要的:

骑手:姓名,电话,实时位置信息等;

商家:店名,位置,菜品,价格信息等;

顾客:姓名,电话,住址信息等;

        这些成员变量就是根据实际需求来定义的。对于这些类,他们之间也会有交互,需要实现交互函数,这就是后话了。

        类和对象是一种能够将现实生活中的关系相对较好的表现出来,这也是面向对象编程的实际需求。

        与此同时,现实生活中的实体计算机并不认识现实生活中的对象,计算机只认识二进制格式的数据。如果想要让计算机认识现实生活中的实体,用户必须通过某种面向对象的语言,对实体进行描述,然后通过编写程序,创建对象后计算机才可以认识。

考虑显示需求:

        对于商家,他们都有一个特征:他们是卖东西的,需要客户。

        对于骑手,他们的特征是:他们是接单送单的,需要商家的订单。

        对于顾客,他们的特征是:他们是需要产品的,要在商家那里消费的,需要商家。

        据此,我们可以把所有的商家抽象为一类,创建一个商家类;把所有的骑手抽象为一个类,创建一个骑手类;把所有的顾客抽象为一个类,创建一个顾客类。

        类是对象的抽象,对象是类的实际体现。

        类的属性和功能来源于生活中的实际需要。

 

用一张图总结:

 

完~

未经作者同意禁止转载 

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。