概述

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. 按ECS退出全屏模式

    <!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/htm ...

  2. UEFI手札

    基于Intel TianoCore衍生的EDK-II诞生的UEFI,用来取代Legacy BIOS. INF文件 Module Information File,模块描述文件.Module可以是可执行 ...

  3. daemon(守护、服务员)-t1.setDaemon(true) - 设置为守护线程

    daemon(守护.服务员)t1.setDaemon(true) - 设置为守护线程 class KTV extends Thread{ public void run(){ try { Thread ...

  4. tjuthesis 图标题左对齐修改办法

    图标题格式默认是居中的. 将 format 文件里定义图表标题样式部分的 \centering 删去,可变为左对齐. 如下: %% 定制浮动图形和表格标题样式\makeatletter\long\de ...

  5. 职位-CHO:CHO

    ylbtech-职位-CHO:CHO 首席人力资源官(Chief Human Resource Officer),简称CHO.是具有制定集团化经营的公司人力资源的战略规划,并监督执行,负责建立畅通的沟 ...

  6. 类StringBuffer

    1字符串声明和创建 public StringBuffer() 无参构造函数 public StringBuffer(int capacity) 指定容量的字符串缓冲区对象 public String ...

  7. 16/7/7_PHP-构造\解析函数

    昨天又问老师问题,老师还是强调要用博客之类记录下每天的学习的习惯. 我个人的想法是一些知识点不用笔记一下 在脑海的理解不是太深.但是老师都这么说了我老师乖乖的记录下今天的学习的一些知识.心得.技巧等等 ...

  8. source ~/.bash_profile是什么意思

    ~ 这个符号表示你的家目录,.bash_profile 是一个隐藏文件,主要是用来配置bash shell的,source -/.bash_profile 就是让这个配置文件在修改后立即生效.

  9. Oracle删除表时候有外键 不能删除

    SELECT    A .constraint_name,    A .table_name,    b.constraint_nameFROM    user_constraints A,    u ...

  10. 05.vue-resource的基本使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...