C++静态成员变量初始化和赋值

C++静态成员变量初始化和赋值1 背景有这样一套会话机制 CSession 为会话对象 CSessionMana 为会话管理类 在 CSession 会话需要销毁时 CSession 主动发送消息给 CSessionMana 销毁 session 同时 CSession 是一个基类 子类通过继承 CSession 实现不同的 session 处理 实现主要考虑三个方面 创建 处理 销毁 通过不同的 server 创建不同的 session

1.背景

有这样一套会话机制,CSession为会话对象,CSessionManager为会话管理类,在CSession会话需要销毁时,CSession主动发送消息给CSessionManager销毁session。同时CSession是一个基类,子类通过继承CSession实现不同的session处理。

实现主要考虑三个方面(创建、处理、销毁):

  1. 通过不同的server创建不同的session会话;
  2. 子类通过CSession提供的虚函数接口实现多态;
  3. 通过消息对象指针发送消息给CSessionManager销毁session;

问题卡在session的销毁:

CSessionManager通过消息队列模板类创建消息对象,保存消息对象指针信息,并且有一个线程专门接收该对象发送的消息。那么CSession会话类也需要知道和保存消息对象指针。

先前有类似情况,消息对象指针是通过构造传参保存下来的。但现在CSession作为一个基类(要被继承),显然通过构造传参是非常不合理的,并且我希望CSession只保存一份消息对象指针(static成员变量),提供唯一 一个发送消息的接口给子类。

大致代码如下:

typedef struct { 
    int connfd; int keepfd; /*是否保留fd:1-是,其他-否*/ }SocketSessionExp; //session会话基类(HttpSession、RtspSession继承该类) class CSession { 
    friend class CSessionManager; public: CSession(); virtual ~CSession(); protected: static void sendMessage(SocketSessionExp &expMessage);//希望CSession对象和子类能通过这个唯一接口发送消息给CSessionManager销毁该CSession会话 private: static TMessageQue<SocketSessionExp> *m_exception_msq;//TMessageQue为消息队列模板类 } //会话管理类 class CSessionManager { 
    public: static CSessionManager* instance(); //单健类 private: CSessionManager(); { 
    m_exception_msq = new TMessageQue<SocketSessionExp>(); CSession::m_exception_msq=m_exception_msq; } ~CSessionManager();//不是重点未给出 private: static TMessageQue<SocketSessionExp> *m_exception_msq;//在构造函数中new一个类对象 std::map<int,CSession*> m_sessionMap; } 

该模块编译时没报错,链接时报错提示:

undefined reference to `Network::CSession::m_exception_msq' 

2.试错

CSessionManager是CSession的友元类,可直接访问CSession的私有成员和保护成员。也尝试通过函数、局部CSession等方式来完成m_exception_msq的赋值,均报错。

3.分析与百度

class CSession { 
    friend class CSessionManager; public: CSession(); virtual ~CSession(); private: static TMessageQue<SocketSessionExp> *m_exception_msq;//TMessageQue为消息队列模板类 } 

分析-有用信息:

  1. 在如上代码中,m_exception_msq只是声明,并没有定义和初始化。
  2. “undefined reference to”是未定义……;
  3. 项目中有地方使用静态变量的地方都在.cpp文件上方进行了初始化(实际是定义–>初始化)。

分析推测:应该是m_exception_msq未定义。

在.cpp文件中添加如下代码:

//xxx.cpp TMessageQue<SocketSessionExp>* CSession::m_exception_msq=NULL; 

编译成功、链接成功、通过打印信息也看到CSession::m_exception_msq在CSessionManager构造中完成了赋值,问题解决了。

这里一方面是对static成员变量的理解不到位,另一方面是分析的时候没有抓住有效信息浪费了不少时间。(“undefined reference to”)

4.C++静态成员变量

C++的变量的类型大致有普通成员变量、静态成员变量、成员常量这三种,还有一种组合的静态成员常量。

这里说一下C++静态成员变量,在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。

static成员的所有者是类本身和对象,但是多个对象拥有一样的静态成员。从而在定义对象时不能通过构造函数对其进行初始化; 静态成员不能在类定义里边初始化,只能在class body外初始化; 静态变量依旧符合public、private、protect特性; 静态成员函数没有this指针,它不能返回非静态成员,因为除了对象会调用它外,类本身也可以调用 。

C++静态成员变量:

  1. 必须在外部定义和赋值;
    • 不能在 main() 函数中定义
    • 不能在类的构造函数中定义
  2. 必须要定义静态变量,否则该变量没有内存空间(类中只是申明) ;
  3. 类本身可以直接调用静态变量
  4. 静态变量依旧符合public、private、protect特性

C++成员变量声明、初始化、赋值说明列表:

数据成员类型 normal const static static const
类内直接初始化(在声明时就赋值) ×
先声明再通过初始化列表赋初值 × ×
先声明再在构造函数体里赋初值 × × ×
先声明再在类外赋初值 × ×

5.C++静态成员方法

1、静态方法可以被类直接调用,但是同静态变量一样符合public、private、protect特性

2、静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。

3、静态成员函数不可以同时声明为 virtual或后缀const 函数。因为virtual就是用来区分是哪个对象调用了他,与静态方法矛盾。而后缀const是用来修饰this指针的,静态变量中不包含this指针。

参考资料:
https://blog.csdn.net/nwd0729/article/details/
https://blog.csdn.net/buknow/article/details/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232884.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • VS Code关闭eslint校验

    VS Code关闭eslint校验一、产生原因:在编写vue代码的时候,一直因为格式问题报错,按照要求改了格式,虽不报错,但当选择格式化文档,就会再次报错,所以需要关闭格式校验功能。二、解决办法:①:若报错,可将鼠标放在报错位置,按照提示内容,单机右键,选择快速恢复;但后期影响继续存在②:关闭校验功能步骤:1.点击左下角的设置图标并选择设置2.搜索eslint,如图并勾选可取消报错:3.重启VSCode,编译时不再报错…

    2022年6月11日
    68
  • 小鹤双拼入门和小鹤音形的搜狗输入法配置方法[通俗易懂]

    小鹤双拼入门和小鹤音形的搜狗输入法配置方法[通俗易懂]记忆口诀秋闱皒软月,韵书迟落撇。阿宋穷带份羹,航岸快赢良况。邹霞夸草追鱼滨,鸟眠小鹤双拼。iueieuanue,unui_oie图月,书痴aongaieneng,anganing_ang建安,快赢,良况ou_aaouiin,iaoian瞎夸,追鱼记忆口诀①(官方版):QiuWeiRuanT_ue_veYunU_shuI_chiSong_iongDaiFenGengHangJ_an秋闱软月云梳翅,松拥

    2022年6月29日
    203
  • js 后退刷新[通俗易懂]

    js 后退刷新[通俗易懂]history.back()和history.go(-1)都可以实现返回上一页并不刷新向要页面后退刷新使用:window.location.href=document.referrer;即可实现

    2022年7月25日
    7
  • 前端json字符串转json对象_list对象转json

    前端json字符串转json对象_list对象转jsonjson字符串转json对象varobj=eval(‘(‘+str+’)’);或者varobj=str.parseJSON();//由JSON字符串转换为JSON对象或者varobj=JSON.parse(str);//由JSON字符串转换为JSON对象

    2022年10月7日
    4
  • 《深入解析Hello,World》 :第三章 java源代码是怎样变成class文件的

    《深入解析Hello,World》 :第三章 java源代码是怎样变成class文件的javac实现原理编译器原理

    2022年5月27日
    24
  • html静态网页设计代码_静态网页设计心得

    html静态网页设计代码_静态网页设计心得第一周:HTML写静态网页1.HTML理论介绍及常用格式(1).HTML主体格式&lt;!DOCTYPEhtml&gt;&lt;html&gt; &lt;head&gt;  &lt;metacharset="utf-8"/&gt;  &lt;title&gt;&lt;/title&gt; &lt;/head&gt; &lt;body&gt;   &

    2022年9月21日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号