概述

static主要有三种使用方式,其中前两种在C/C++中使用,第三种只在C++语言中使用

1)静态局部变量

2)静态全局变量/函数

3)静态成员变量/函数

3 静态成员变量/函数

3.1静态成员变量

静态成员是C++所特有的,在类内数据成员的声明前加上关键字static,该数据成员就是类的静态数据成员了。

class CGame
{
public:
CGame();
virtual ~CGame();
void drawGameArea();
void drawGameInfo();
void changeInfo();
void run();
bool checkFailed();
bool checkLevel();
public:
static const int KLEFT;
static const int KUP;
static const int KWIDTH;
static const int KHEIGHT;
static const int KSCORE_OFFSET;
static const int KLEVEL_OFFSET;
private:
CFood *m_pFood;
CSnake *m_pSnake;
int m_iScore; //游戏得分
int m_iLevel; //关卡设置
};

以上的代码中

	static const int KLEFT;
static const int KUP;
static const int KWIDTH;
static const int KHEIGHT;
static const int KSCORE_OFFSET;
static const int KLEVEL_OFFSET;

就是类的静态成员。

static成员变量的特点:

  • 静态数据成员和普通数据成员一样遵从public,privateed,protected访问规则
  • 静态数据成员初始化的格式为:
<数据类型><类名>::<静态数据成员名>=<值>

实例如下:

//静态成员变量的初始化
const int CGame::KLEFT = 5;
const int CGame::KUP = 2;
const int CGame::KWIDTH = 70;
const int CGame::KHEIGHT = 20;
const int CGame::KSCORE_OFFSET = 50;
const int CGame::KLEVEL_OFFSET = 65;
  • 无论类的对象被定义了多少个,静态数据成员在程序中只有一份拷贝,由该类型的所有对象共享访问。

    类中定义了静态成员变量,一定要记得初始化!

    参考:https://www.cnblogs.com/Manual-Linux/p/10996457.html 《C++使用静态类成员时出现的一个问题》

3.2静态成员函数

静态成员函数同静态成员变量一样,它为类服务而不是为类的具体对象服务。一般普通成员函数都隐含一个this指针,this指针指向类的对象本身,而静态成员函数不存在this指针,因为静态成员函数不属于任何对象,它属于类。静态成员函数无法访问类对象的非静态成员(包括非静态数据成员和非静态成员函数)。

可以采用下述格式进行静态成员函数的调用

<类名>::<静态成员函数名>(<参数表>)

小心陷阱

1 静态成员函数可以访问静态成员,但绝不能访问非静态成员。

2 静态成员不能声明为虚函数。这是因为静态成员函数在对象实例未生成前便可以调用。而如果对象实例未产生,虚函数调用使用的虚函数表未生成,导致虚函数调用时不知调用子类的虚函数还是父类的虚函数

【实际的应用】

在俄罗斯方块项目中,为了绘制方便,需要改变光标的位置,因此需要实现一个函数

void gotoxy(int x,int y)

在C++的体系中,不希望把gotoxy()作为一个游离的全局函数,所以用一个类来单独的实现这个函数,同时又希望这个函数可以随时随地的使用,就把它编写为一个类的静态成员函数。如果真的声明成一个类的函数,每次用的时候,都要实例化一个对象,这样就太麻烦了。

gotoxy()函数的实现

#include "CCommFunc.h"
#include<Windows.h> void CCommFunc::gotoxy(int x, int y)
{
COORD cd;
cd.X = x;
cd.Y = y;
//SetConsoleCursorPosition()函数用来设置控制台光标位置
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),cd);
}

该函数的使用

/*******************************************
Description: 绘制主窗体程序
Input: int needLayers 当前通关所需要的层数
int currentLayers 当前已经消去的层数
Ouput: 无
Return: 无
Others: 无
*********************************************/
void CInfoBoard::drawInfoBoard(int needLayers, int currentLayers)
{
if (needLayers < currentLayers)
{
return;
}
CCommFunc::gotoxy(this->m_offsetX,this->m_offsetY);
cout << "------------------------";
CCommFunc::gotoxy(this->m_offsetX,this->m_offsetY + 1);
cout << " NEED: " << needLayers << " ";
CCommFunc::gotoxy(this->m_offsetX, this->m_offsetY + 2);
cout << " NOW: " << currentLayers << " ";
CCommFunc::gotoxy(this->m_offsetX, this->m_offsetY + 3);
cout << "-------------------------";
}
  • 2019-7-16 更新:静态成员函数没有this指针

今天在写代码的时候,Create()函数在类中的声明如下所示

static IController* Create(IControllerFactory* f);

在实现Create()函数时候,不自觉的使用了this,导致编译器报错

IController* IController::Create(IControllerFactory* f)
{
if(!f)
{
return nullptr;
}
this->m_f = f;
IController* c = f->CreateC();
// c->m_f = f;
c->m = f->CreateM();
c->v = f->CreateV(); return c;
}

提示错误为:

error: C2355: “this”: 只能在非静态成员函数或非静态数据成员初始值设定项的内部引用

【编码的法则】谨慎的使用static的更多相关文章

  1. .Net(c#)汉字和Unicode编码互相转换

    {"Tilte": "\u535a\u5ba2\u56ed", "Href": "http://www.cnblogs.com&q ...

  2. 中文字符串转换为十六进制Unicode编码字符串

    package my.unicode; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Uni ...

  3. java-base64编码和解码

    一.反射/*** * encode by Base64 */ public static String encodeBase64(byte[]input) throws Exception{ Clas ...

  4. Java生成BASE64编码

    1.所需jar包: BASE64Encoder.jar 2.在导包过程中,可能会出现工程不识别的情况.即:不能找到BASE64Encoder的jar包.此时,可以有两种方法解决这个问题: a.  只需 ...

  5. C# Unicode编码

    为了避免在浏览器中传输数据的时候出现中文乱码,我们可以将内容进行URL编码,当然也可以将内容进行UNICODE编码.将汉字进行UNICODE编码,如:"王"编码后就成了" ...

  6. Bencode的编码与解码

    开源地址: https://github.com/CreateChen/Bencode Nuget: Install-Package Bencode 1. Bencode规则 BEncoding是Bi ...

  7. Java安全编码之用户输入

    0x00 安全引言 1.传统Web应用与新兴移动应用 (1)传统Web应用:浏览器 HTTP 服务器(2)新兴移动应用:APP HTTP 服务器 从安全角度看,传统Web应用与新兴移动应用没有本质区别 ...

  8. 普通字符串与Hex编码字符串之间转换

    import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Hex; public clas ...

  9. 【C#基础】实现URL Unicode编码,编码、解码相关整理

    1.Unicode编码 引用系统 System.Web using System.Web; string postdata = "SAMLRequest=" + HttpUtili ...

随机推荐

  1. 线性回归 r python 比较

    w http://blog.sina.cn/dpool/blog/s/blog_70f632090101bp8u.html

  2. vue +ts 的一次踩坑日记

    在vue的方法里面写事件的时候比如写一个路由跳转,方法大概如下:  goBack1() {            console.log(this);            this.$router. ...

  3. PJSIP库设置Via地址

    好记性不如烂笔头,解决项目问题,调试代码跟踪到PJSIP 设置Via地址位置,记录下来,以备后用. PJSIP库在方法stateless_send_transport_cb中设置Via地址值,该方法在 ...

  4. 使用wxpy模块了解微信好友

    网上看了一篇python文章,内容简单有趣,正好可以练习一下.原文连接:http://mp.weixin.qq.com/s/oI2pH8uvq4kwYqc4kLMjuA 一.环境:Windows+py ...

  5. fedora安装ep,forge,fusion等第三方软件库

    fedora安装ep,forge,fusion等第三方软件库 官方的发行版 抛弃了有 版权争议的 软件, 特别是 包括很多第三方的 多媒体软件, 如播放 mp3, flv等的软件 解码器 这就要靠 使 ...

  6. Python字典的json格式化处理(换行与不换行)

    Prefer = {"jim": {"War": 1.9, "the big bang": 1.0, "The lord of w ...

  7. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_01 File类_6_File类判断功能的方法

    exists true表示路径是存在的 不存在的路径 不存在的路径返回false 相对路径的文件的判断 ‘ 不存在的相对路径 isDirectory和isFile 路径是不存在的 用这个方法之前最好先 ...

  8. 查看linux显卡序列

    1 lspci -vnn | grep VGA -A 12会输出显卡的硬件信息,第一行的第二个[]内是显卡的序列号2 在网站http://pci-ids.ucw.cz/read/PC/ 下方输入序列号 ...

  9. WPF与DevExpress之——实现类似于安装程序下一步下一步的样式窗体

    话不多说先上图  点击下一步  跳转到第二页  项目准备: 1.DevExpress 19/18/17(三个版本都可以) 2.Vs2019 3..Net framework>4.0 项目结构: ...

  10. python正则表达式整理

    正则表达式在处理字符串时很大的作用,爬虫中也经常用到,下面就将一些常用正则表达式做一整理记录,方便以后查看. ^d   表示匹配以d开头的字符串 .      表示匹配任意字符串 *     表示前面 ...