zoukankan      html  css  js  c++  java
  • 【编码的法则】谨慎的使用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”: 只能在非静态成员函数或非静态数据成员初始值设定项的内部引用

  • 相关阅读:
    聊一聊所谓的B端C化
    NetCore3.1IIS其他网站出现HTTP503无法访问解决办法
    技术方案模板 fn
    技术方案模板
    composer的常用操作(composer 2.2.1)
    thinkphp6: 用validate验证参数合法性(thinkphp 6.0.9/php 8.0.14)
    thinkphp6: 从6.0.9升级(php 8.0.14)到 6.0.10lts版本(php 8.1.1)
    thinkphp6: 自定义配置文件(php 8.1.1 / thinkphp v6.0.10LTS)
    linux(ubuntu21.10):为chrome安装jsonvue(chrome 96)
    thinkphp6:mysql数据库使用事务(php 8.1.1 / thinkphp v6.0.10LTS)
  • 原文地址:https://www.cnblogs.com/Manual-Linux/p/11017751.html
Copyright © 2011-2022 走看看