永发信息网

C++类中定义数据成员的类型的几种方式

答案:1  悬赏:0  手机版
解决时间 2021-02-27 02:24
C++类中定义数据成员的类型的几种方式
最佳答案
一、简述
C++中除了在类中简单声明数据成员外,还可创建static数据成员,const成员,引用成员,const引用等。
—————————————————————
二、.静态数据成员
应用背景:有时没必要让所有类的对象都包含某个变量的副本,或者说你需要一个只对类有意义的数据成员,而不适用于针对某个对象。比如设计一个电子表格的类,每个电子表格都有一个唯一的ID,我们可以为类设计一个从0开始的计数器,这样每个对象可从这个计数器得到自身的ID,但显然没必要为每个对象包含这个计数器,这样的麻烦是因为你还得让计数器保持同步。解决的办法是使用静态数据成员。静态数据成员属于类,而不具体属于类的某个实例,可将静态数据成员当做属于类的全局变量,所有该类的实例对象都只有和可见这么一份。比如:
class MyClass{
//......
protected: static int counter_=0;
}

注意:在C++11中是可以在类的定义中初始化静态成员的。下面介绍具体的两个用法
1.在类的方法内访问静态数据成员
在类的方法内部可像使用普通数据成员一样使用静态数据成员。比如:
类的声明部分:
class MyClass{
public: //.....
int get_id() const; protected: //.....
static int count=0; int id_;
};

类的实现部分:
MyClass::MyClass(int in_width,int int height):
width_(in_width),height_(height)
{
id_=count++; //......}

也就是说在构造函数中可以访问静态数据成员counter就像访问普通数据成员一样。
2.在方法外访问静态数据成员
访问控制限定符也适用于静态数据成员。上面的counter是protected的,因此不能在类外访问,若是公有的则可,具体也是用作用域解析运算符指出这个变量是类的一部分,例如:
int i=MyClass::count;

当然,并不建议这么用,而是为类提供get/set方法来授权访问权限。如果想要访问静态数据成员,应该提供静态的get/set方法。
—————————————————————
三、常量数据成员
类的数据成员还可以声明为cosnt,这意味着在创建并初始化之后数据成员的值不能再改变。然而在对象层次上常量通常没有意义,因此常量数据成员通常也是静态的。如果某个常量只适用于类,应该使用静态常量数据成员而不是全局常量。例如设计一个表格类时,我们可能会指定表格表格的最大高度和宽度,这个值可设置成一个静态常量数据成员,当用户想要创建的表格高度或宽度大于该最大值时使用最大值,代码片段如下:
class SpreedSheet{
public: //......
static const int kMaxHeight=100; static const int kMaxWidth=100;
};

为什么说在对象层次上常量通常没有意义呢,私下认为,对象本身就是个变量,但对象里面却包含常量很不可思议,是不?换句话说:变得东西里含有不变的成分,那么不变的那部分还有什么意义呢。
有了上述类中的静态常量,我们就可以在类的构造函数中这样使用这个新的常量了。
SpreedSheet::SpreadSheet(int width,int hegiy):
width_(width<<span>kMaxWidth?width:kMaxWidth), height(height<<span>kMaxHeight?height:kMaxHight)
{ id_=count++;
//......}

这样当输入宽度或高度大于最大值时,会自动使用最大高度和宽度构造对象。由于kMaxHeight以及kMaxWith是公有的,因此可在程序的任何位置对其进行访问。但必须带作用域解析符,以说明该变量是哪个类的一部分。例:
cout<<span><<span>SpreadSheet::kMaxHeight<<endl;

—————————————————————
四、引用数据成员
考虑一个架构问题:电子表格如何与应用程序通信?至少我们应该让应用程序存储电子表格,电子表格也该存储应用程序对象的引用。即具体来说SpreadSheet类必须知道SpreadSheetApplication类,SpreadsheetApplication类也必须知道SpreadSheet类,即通信是双方的,必须相互认识才能有效传递消息么。那么这里就存在一个问题,我们在类的实现里需要相互#inlcude,这就是传说中的循环引用问题,相互#include是不能解决问题的。解决方案是在其中一个头文件中使用前置声明。比如下面含前置声明的类的定义:
class SpreadsheetApplication; //前置声明classSpreadsheet{
public: Spreadsheet(int in_width,Int in_height,SpreadsheetApplication& the_app); //......
protected: //...... SpreadsheetApplication& the_app_;
};

这里类的定义将一个SpreadsheetApplicatin引用作为数据成员添加进来,建议使用引用,因为引用总是引用一个SpreadsheetApplication,而指针无法保证这点。在类的构造函数中,每个Spreeadsheet都得到一个应用程序的引用。若不引用某些事物,引用将无法存在,因此在构造函数中必须给the_app_一个值。
Spreadsheet::Spreadsheet(int in_width,int in_height,SpreadsheetApplication & the_app):widthe_(in_width<<span>kMaxWidth?in_width:kMaxWidth),height_(in_height<<span>kMaxHeight?in_height:kMaxHight),the_app_(the_app){}

也就是说类中的引用数据成员必须在类的所以构造函数中初始化它。包括复制构造函数:
Spreeadsheet::Spreadsheet(const Spreadsheet& src): the_app_(src.the_app_){}

在初始化一个引用之后,不能改变它的引用对象。因此无需在赋值运算符中对引用赋值。
—————————————————————
五、常量引用数据成员
和普通引用可以引用常量对象一样,引用成员也可以引用常量对象。可以这么看,常量不过是普通的一个特殊而已。例如:
class Spreadsheet{
public:
Spreadsheet(int in_width,int in_height,const SpreadsheetApplication& the_app); //......
protected: //......
const SpreadsheetApplication& the_app_;
};

常量引用和非常量引用的一个重要区别是:比如这里的常量引用SpreadsheetApplication的数据成员 the_app_只能调用SpreadsheetApplication对象上的常量方法。如果试图通过常量引用调用非常量方法,编译报错。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
vivo X6A有Root&第三方Recovery相关的资
荆门山宾馆这个地址在什么地方,我要处理点事
2019年小学基础训练二年级数学上册青岛版五四
南湖东园一区北门地址有知道的么?有点事想过
怎么才能分辨金毛巡回犬是不是纯种的?
梦见初中同学
下列我国古代衣着织物三种原料使用的先后顺序
默写(18分)【小题1】.回看射雕处, 。《观
The building, in the shape of an egg, is
帮我申请口口邮箱
百色玉柴汽车贸易服务有限公司这个地址在什么
相应的近义词是什么
图示等跨连续梁在哪一种荷载布置作用下,bc跨
我家新做的房子,瓦是蓝色的,门是铜色额别墅
我国要加快燃煤电厂的(  )治理,以减轻酸
推荐资讯
良友百货我想知道这个在什么地方
好日子砂锅居在什么地方啊,我要过去处理事情
配股是买入还是卖出操作
小红帽童装地址有知道的么?有点事想过去
未经主人允许下,私自拆家里的院子,算触犯什
南溪北路/X024(路口)我想知道这个在什么地方
双子座的守护花是什么
南山先生画室怎么去啊,有知道地址的么
国强百货商场怎么去啊,有知道地址的么
同心缘饭店怎么去啊,有知道地址的么
2017年4月12日杭州宁安地震
签售会之前很多人说要拼签售是什么意思
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?