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

 我来答
匿名用户
推荐于2018-05-06
展开全部
一、简述
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对象上的常量方法。如果试图通过常量引用调用非常量方法,编译报错。
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式