【编码的法则】谨慎的使用static
概述
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的更多相关文章
- .Net(c#)汉字和Unicode编码互相转换
{"Tilte": "\u535a\u5ba2\u56ed", "Href": "http://www.cnblogs.com&q ...
- 中文字符串转换为十六进制Unicode编码字符串
package my.unicode; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Uni ...
- java-base64编码和解码
一.反射/*** * encode by Base64 */ public static String encodeBase64(byte[]input) throws Exception{ Clas ...
- Java生成BASE64编码
1.所需jar包: BASE64Encoder.jar 2.在导包过程中,可能会出现工程不识别的情况.即:不能找到BASE64Encoder的jar包.此时,可以有两种方法解决这个问题: a. 只需 ...
- C# Unicode编码
为了避免在浏览器中传输数据的时候出现中文乱码,我们可以将内容进行URL编码,当然也可以将内容进行UNICODE编码.将汉字进行UNICODE编码,如:"王"编码后就成了" ...
- Bencode的编码与解码
开源地址: https://github.com/CreateChen/Bencode Nuget: Install-Package Bencode 1. Bencode规则 BEncoding是Bi ...
- Java安全编码之用户输入
0x00 安全引言 1.传统Web应用与新兴移动应用 (1)传统Web应用:浏览器 HTTP 服务器(2)新兴移动应用:APP HTTP 服务器 从安全角度看,传统Web应用与新兴移动应用没有本质区别 ...
- 普通字符串与Hex编码字符串之间转换
import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Hex; public clas ...
- 【C#基础】实现URL Unicode编码,编码、解码相关整理
1.Unicode编码 引用系统 System.Web using System.Web; string postdata = "SAMLRequest=" + HttpUtili ...
随机推荐
- [CSP-S模拟测试]:飘雪圣域(莫队)
题目描述 $IcePrincess\text{_}1968$和$IcePrince\text{_}1968$长大了,他们开始协助国王$IceKing\text{_}1968$管理国内事物. $IceP ...
- Mybatis传多个参数(三种解决方案) mapper.xml的sql语句修改!
第一种 Public User selectUser(String name,String area); 对应的Mapper.xml <select id="selectUser&qu ...
- 国内npm镜像使用方法
npm全称Node Package Manager,是node.js的模块依赖管理工具.由于npm的源在国外,所以国内用户使用起来各种不方便.下面整理出了一部分国内优秀的npm镜像资源,国内用户可以选 ...
- 《SQL Server 2012 T-SQL基础》读书笔记 - 7.进阶查询
Chapter 7 Beyond the Fundamentals of Querying window function是什么呢?就是你SELECT出来一个结果集,然后对于每一行,你都想给它对应一个 ...
- day41—JavaScript运动的停止条件
转行学开发,代码100天——2018-04-26 前面学过了JavaScript运动的两种常用情形:匀速运动与缓冲运动.在这两种运动的处理过程中最大的区别在于速度的处理和到达目标点的处理. 即本文需要 ...
- MDX 入门
之前用到的SQL,解释:结构化查询语言(Structured Query Language)(发音:/ˈes kjuː ˈel/ "S-Q-L"),是一种特殊目的的编程语言,是一种 ...
- 使用spring配置类代替xml配置文件注册bean类
spring配置类,即在类上加@Configuration注解,使用这种配置类来注册bean,效果与xml文件是完全一样的,只是创建springIOC容器的方式不同: //通过xml文件创建sprin ...
- tail()函数
与head()函数类似,默认是取dataframe中的最后五行. 函数源码: def tail(self, n=): """ Returns last n rows &q ...
- Robot Framework-DatabaseLibrary(MySql) API
API 参数 说明 Check If Exists In Database 查询语句 数据库中存在:存在,则为PASS,不存在,则为FAIL Check If Not Exists In Databa ...
- 【Unity Shader】---入门知识点
着色器声明(“名字”)Shader "ShaderDiffuseExample" { 一.属性定义(作用:外部传入参数) 属性定义语法:PropName("Display ...