C++ class中的静态(static)成员

C++ class中的静态(static)成员

(1)       静态数据成员

   ①一般地静态数据成员在该类定义之外被初始化,如同一个成员函数被定义在类定义之外一样。在这种定义中的静态成员的名字必须被其类名限定修饰,例如下面是_interestRate的初始化

// 静态类成员的显式初始化

#include "account.h"

double Account::_interestRate = 0.0589;

 

   ②静态数据成员的初始化不应该被放在头文件中,而应该放在含有类的非inline 函数定义的文件中。静态数据成员可以被声明为任意类型。例如:

 

#include <string>

class Account

{

// ...

private:

    static const string name;

};

const string Account::name( "Savings Account" );

 

作为特例,整型的const 静态数据成员可以在类体中用一常量值初始化。例如,如果决定用一个字符数组而不是string 来存储账户的姓名那么我们可以用int 型的const 数据成员指定该数组的长度,例如:

 

// 头文件

class Account {

// ...

private:

static const int nameSize = 16;

static const char name[nameSize];

};

// 文本文件

const int Account::nameSize; // 必需的成员定义

const char Account::name[nameSize] = "Savings Account";

 

用常量值作初始化整型的const 静态数据成员是一个常量表达式(constant expression)。如果需要在类体中使用这个被命名的值,那么,类设计者可声明这样的静态数据成员。例如,因为const 静态数据成员nameSize是一个常量表达式,所以类的设计者可以用它来指定数组数据成员name 的长度。在类体内初始化一个const 静态数据成员时,该成员必须仍然要被定义在类定义之外。但是因为这个静态数据成员的初始值是在类体中指定的所以在类定义之外的定义不能指定初始值。

因为name 是一个数组,不是整型,所以它不能在类体内被初始化。任何试图这么做的行为都会导致编译时刻错误,例如:

 

class Account {

// ...

private:

static const int nameSize = 16; // ok: 整型

static const char name[nameSize] =

"Savings Account"; // 错误

};

name 必须在类定义之外被初始化。

这个例子还说明了一点我们注意到成员nameSize 指定了数组name 的长度,而数组name的定义出现在类定义之外

const char Account::name[nameSize] = "Savings Account";

nameSize 没有被类名Account 限定修饰。尽管nameSize 是私有成员,但是name的定义仍没有错。如同类成员函数的定义可以引用类的私有成员一样,静态数据成员的定义也可以。静态数据成员name的定义是在它的类的域内,当限定修饰名Account::name被看到之后,它就可以引用Account 的私有数据。

 

③静态数据成员的访问

1.     在类的成员函数中可以直接访问该类的静态数据成员,而不必使用成员访问操作符:

inline double Account::dailyReturn()

{

    return( _interestRate / 365 * _amount );

}

2.     在非成员函数中,我们必须以如下两种方式访问静态数据成员:

   I. 使用成员访问操作符

class Account {

// ...

private:

friend int compareRevenue( Account& , Account* );

// 余下部分未变

};

// 引用和指针参数来说明对象和指针访问

int compareRevenue( Account &ac1, Account *ac2 )

{

double ret1, ret2;

ret1 = ac1._interestRate * ac1._amount;

ret2 = ac2->_interestRate * ac2->_amount;

// ...

}

ac1._interestRate 和ac2->_interestRate都引用静态成员Account::_interestRate

    

      II. 访问静态数据成员的另一种方法,是用被类名限定修饰的名字直接访问它

// 用限定修饰名访问静态成员

if ( Account:_interestRate < 0.05 )

当我们不通过类的成员访问操作符访问静态数据成员时必须指定类名以及紧跟其后的域操作符        Account:: 。

因为静态成员不是全局对象所以我们不能在全局域中找到它下面的friend 函数compareRevenue()的定义与刚刚给出的等价

 

int compareRevenue( Account &ac1, Account *ac2 )

{

double ret1, ret2;

ret1 = Account::_interestRate * ac1._amount;   //因为是friend函数,才可以访

//私有的静态成员变量_interestRate

ret2 = Account::_interestRate * ac2->_amount;

// ...

}

注意:静态数据成员的“惟一性”本质(独立于类的任何对象而存在的惟一实例),使它能够以独特的方式被使用,这些方式对于非static 数据成员来说是非法的

①静态数据成员的类型可以是其所属类,而非static 数据成员只能被声明为该类的对象的指针或引用。例如:

class Bar {

public:

// ...

private:

static Bar mem1; // ok

Bar *mem2; // ok

Bar mem3; // 错误

};

2 静态数据成员可以被作为类成员函数的缺省实参,而非static 成员不能。例如:

extern int var;

class Foo {

private:

int var;

static int stcvar;

public:

// 错误: 被解析为非 static 的 Foo::var

// 没有相关的类对象

int mem1( int = var );

 

// ok: 解析为 static 的 Foo::stcvar

// 无需相关的类对象

int mem2( int = stcvar );

 

// ok: int var 的全局实例

int mem3( int = ::var );

};

 

(2)       静态成员函数

    使用类的静态成员函数来访问类的私有静态数据成员。

    静态成员函数的声明除了在类体中的函数声明前加上关键字static, 以及不能声明为const 或volatile之外,与非静态成员函数相同。出现在类体外的函数定义不能指定关键字static。

静态成员函数没有this 指针,因此在静态成员函数中,隐式或显式地引用这个指针都将导致编译时刻错误。试图访问隐式引用this 指针的非静态数据成员也会导致编译时刻错误。例如前面给出的成员函数dailyReturn()就不能被声明为静态成员函数,因为它访问了非静态数据成员amount。

我们可以用成员访问操作符点. 和箭头-> 为一个类对象或指向类对象的指针调用静态成员函数,也可以用限定修饰名直接访问或调用静态成员函数,而无需声明类对象。

 

(3)在派生类中的静态数据成员与静态成员函数

class的static data member只有一份实例,被class和class的派生类的所有实例共享。class和class的派生类共用同一块内存中的静态数据成员。

一个简单的例子:

#include <iostream>

using namespace std;

 

class A{

public:

     A(){}

     ~A(){}

     static void SetA(int b){a=b;}

     static int GetA(){return a;}

private:

     static int a;

};

int A::a = 5;

class B : public A{

public:

     B(){}

     ~B(){}

};

int main(){

cout<< "a=" << A::GetA() <<'/n';  //输出5

cout<< "a=" << B::GetA() <<'/n';  //输出5

B::SetA(4);

cout<< "a=" << B::GetA() <<'/n';  //输出4  

cout<< "a=" << A::GetA() <<'/n';  //输出4

return 0;

}  

类的静态函数与函数中的静态数据成员在编译期绑定!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/452396.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用计算机弹可惜不是你,可惜不是你 还是幸亏不是你

一、 你没有再挽留 我也没有再回头 就这样 无风无雨也无晴 无疾而终二、 是我孤陋寡闻不知你心有人三、 如果作业有葬礼,全体学生定当盛装出席.四、 纵使我有千般好 你也看不到 因为你没有一双爱我的眼睛五、 原来暂时共你没缘分 来年先会变得更合衬六、 真的别回头 你有未来 你…

PHP 完整实战23种设计模式

PHP实战创建型模式 单例模式 工厂模式 抽象工厂模式 原型模式 建造者模式 PHP实战结构型模式 桥接模式 享元模式 外观模式 适配器模式 装饰器模式 组合模式 代理模式 过滤器模式 PHP实战行为型模式 模板模式 策略模式 状态模式 观察者模式 责任链模式 访问者模…

Diango博客--16.稳定易用的 Django 分页库,完善分页功能(二)

文章目录0.思路引导1.分页效果概述2.分页思路3.Django 第三方拓展&#xff1a;django-pure-pagination4.自定义模板0.思路引导 1&#xff09;在前面我们通过 Django Pagination 实现简单分页 中&#xff0c;我们实现了一个简单的分页导航。但效果有点差强人意&#xff0c;我们…

回归测试

在集成测试过程中&#xff0c;每当一个新模块结合进来时&#xff0c;程序就发生了变化&#xff1a;建立了新的数据流路径&#xff0c;可能出现了新的I/O操作&#xff0c;激活了新的控制逻辑。在集成测试的范畴中&#xff0c;回归测试是指重新执行已经做过的测试的某个子集&…

不同的写法 其中 1 2 (试了下 没有效果 ,先记载这里把)

转载于:https://www.cnblogs.com/kaibindirver/p/9145455.html

美国西北大学 计算机工程专业排名,[转载]美国西北大学计算机工程研究生最新专业排名...

对于打算去美国西北大学读研究生的学生来讲&#xff0c;美国西北大学研究生申请要求及美国西北大学研究生专业介绍是学生最关心的问题。本文香港介绍美国西北大学研究生申请要求及美国西北大学研究生的专业介绍&#xff0c;帮助更多的学生更好的了解美国西北大学。2016年西北大…

析构函数virtual与非virtual区别

作为通常的原则&#xff0c;如果一个类定义了虚函数&#xff0c;那么它的析构函数就应当是virtual的。因为定义了虚函数则隐含着&#xff1a;这个类会被继承&#xff0c;并且会通过基类的指针指向子类对象&#xff0c;从而得到多态性。 这个类可能会被继承&#xff0c;并且会…

Python:字典列表字符串方法测试

测试的一些Python中的关于字典、列表、字符串的使用方法&#xff0c;放在这里备查。整个测试代码和说明如下&#xff1a; # -*- coding: utf-8 -*- """Python:函数中全是指针传递&#xff0c;而任何变量都是给予一个指针指向一个内存空间"""impo…

什么是确认测试

确认测试也称为验收测试&#xff0c;它的目标是验证软件的有效性。 通常&#xff0c;验证指的是保证软件正确地实现了某个特定要求的一系列活动&#xff1b;确认指的是为了保证软件确实满足了用户需求而进行的一系列活动。 软件有效性的一个简单定义是&#xff1a;如果软件的功…

Diango博客--17.统计各个分类和标签下的文章数

文章目录0.思路引导1.Model 回顾2.数据库数据聚合3.使用 Annotate4.在模板中引用新增的属性0.思路引导 在我们的博客侧边栏有分类列表和标签列表&#xff0c;显示博客已有的全部文章分类。现在想在分类名和标签名后显示该分类或者标签下有多少篇文章&#xff0c;该怎么做呢&am…

HTTP协议中request报文请求方法和状态响应码

一个HTTP请求报文由4部分组成&#xff1a; 请求行&#xff08;request line&#xff09;请求头部&#xff08;header&#xff09;空行请求数据下图给出了请求报文的一般格式&#xff1a; 请求行中包括了请求方法&#xff0c;常见的请求方法有&#xff1a; GET&#xff1a;从服务…

计算机无法安装64位操作系统,为什么我的win7旗舰版service Pack 1 64位操作系统 无法安装(KB2670838) 这个更新...

您好&#xff01;我了解到您遇到关于这边的问题请问无法安装是否出现了什么错误代码提示呢&#xff1f;请参考以下的步骤解决按WindowsR打开cmd里使用下面的命令关闭相关的一些服务&#xff1a;net stop wuauservnet stop cryptSvcnet stop bitsnet stop msiserver完成后&#…

bmon:一个强大的网络带宽监视和调试工具

bmon 是类 Unix 系统中一个基于文本&#xff0c;简单但非常强大的 网络监视和调试工具&#xff0c;它能抓取网络相关统计信息并把它们以用户友好的格式展现出来。它是一个可靠高效的带宽监视和网速估测工具。 它能使用各种输入模块读取输入&#xff0c;并以各种输出模式显示输出…

函数的调用规则(__cdecl,__stdcall,__fastcall,__pascal)

关于函数的调用规则&#xff08;调用约定&#xff09;&#xff0c;大多数时候是不需要了解的&#xff0c;但是如果需要跨语言的编程&#xff0c;比如VC写的dll要delphi调用&#xff0c;则需要了解。 microsoft的vc默认的是__cdecl方式&#xff0c;而windows API则是__stdcall&a…

Linux 下的/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin区别

1、/bin 是所有用户都可以访问并执行的可执行程序。包括超级用户及一般用户。 供所有用户&#xff08;包括root用户和一般用户&#xff09;使用的基本命令&#xff0c;主要有cat,chmod,date,cp,bash等等常用的命令。 2、/usr/bin&#xff1a;系统预装的可执行程序&#xff0c;…

alpha测试和betal测试

如果一个软件是为许多客户开发的&#xff08;例如&#xff0c;向大众公开出售的盒装软件产品&#xff09;&#xff0c;那么绝大多数软件开发商都使用被称为Alpha测试和Beta测试的过程&#xff0c;来发现那些看起来只有最终用户才能发现的错误。 Alpha测试由用户在开发者的场所进…

计算机d盘无法格式化,四种方法解决D盘无法格式化问题

不少朋友系统出现故障&#xff0c;几乎都是选择重装系统的方法来解决问题。系统重装后&#xff0c;不少朋友觉得D盘没有什么重要的东西&#xff0c;就想将其格式化&#xff0c;可是系统出现windows无法格式该驱动器的提示&#xff0c;这是怎么回事呢&#xff1f;D盘无法格式化要…

sqlserver视图

作用 ①简化了操作&#xff0c;把经常使用的数据定义为视图。 ②安全性&#xff0c;用户只能查询和修改能看到的数据。 ③逻辑上的独立性&#xff0c;屏蔽了真实表的结构带来的影响。 对视图的修改&#xff1a;单表视图一般用于查询和修改&#xff0c;会改变基本表的数据&#…

非root用户sudo_ssh免密钥

非root用户sudo_ssh免密钥 目标&#xff1a;从服务器上ssh登陆后sudo免密钥执行相应的命令 环境介绍&#xff1a; 192.168.65.128 my1-222 192.168.65.129 my2-223 192.168.65.130 web224# 步骤一&#xff1a; # 每个节点执行(不是必须&#xff0c;但是建议这样做) cat …

复旦大学和吉大计算机考研选哪个,2016复旦大学VS吉林大学 基于排名角度的比较?...

复旦大学好还是吉林大学好首先&#xff0c;2016复旦大学好还是吉林大学好是近日问得较多的问题之一&#xff0c;小伙伴们有的从吉林大学和复旦大学的地理位置优势角度进行分析&#xff0c;有的从吉林大学和复旦大学的强势专业角度进行PK&#xff0c;有的甚至从吉林大学和复旦大…