本帖最后由 baizy77 于 2018-10-1 21:01 编辑
版权声明 --------------------------------------------------------------------------------------------------------------------- 作者: 女儿叫老白 (白振勇) 转载请注明出处! --------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------
引言: ---------------------------------------------------------------------------- 上节我们讨论了static的两种基本含义,了解了static变量在内存中的位置以及它的生存期。那么,关于static,我们还能知道点啥呢?
正文: ---------------------------------------------------------------------------- 之前讨论的基本是函数内或文件内的static变量,现在我们看一下类内部定义的static变量。 代码清单: ---------------------------------------------------------------------------- // class.h class CMyClass { private: static double s_dCoef; };
// class.cpp double CMyClass::s_dCoef= 0.13f; ---------------------------------------------------------------------------- 从上述代码中,我们可以看出对一个类的内部static变量的定义以及初始化的语法。大家可能会有疑问,static变量不是仅在定义处初始化一次吗,上面的代码中怎么把定义和初始化分开了呢,其实大家不用担心,编译器负责保证该语法的正确性。假如我们使用一个静态的类对象作为成员变量,代码如下: 代码清单: ---------------------------------------------------------------------------- // class2.h class CData { public: CData(int num, int max):m_num(num),m_max(max) {} ~CData() {} private: int m_num; int m_max; }; class CMyClass2 { private: static CData s_data; }; // class2.cpp CData CMyClass2::s_data(3, 99); ---------------------------------------------------------------------------- 从上述最后一行代码可以看出,CMyClass2的静态成员s_data采用构造函数进行初始化,这样可以更加显示的说明,静态对象在定义时初始化。 如果成员变量是一个静态数组,那么情况也是一样的: 代码清单: ---------------------------------------------------------------------------- // class.h class CMyClass { private: static const int s_ids[]; static const std::string s_addresses[5]; }; // class.cpp const int CMyClass::s_ids[] = { 1, 2, 3, 4, 5, 6 }; const std::string CMyClass::s_addresses[] = { "hello", "here", "is", "the", "code" }; ---------------------------------------------------------------------------- 说了这这么多,类的静态成员变量有啥用呢?有时我们需要提供一个跟该类相关的数据,但是使用全局对象又不安全,因为它可以被任何人以extern方式修改,而且很容易出现命名冲突。所以,我们可以用类内部的静态对象,它既可以像全局变量那样存储,又可以限定其作用域。 除了静态成员变量,我们还可以为类提供静态成员函数,类的静态成员函数定义如下: 代码清单: ---------------------------------------------------------------------------- // expression.h // 表达式解析类 class CExpressionParser { public: /** *@brief 将中缀表达式拆分为字符串数组。 *@param[in] strExpression 待解析的表达式 *@param[out] B 解析后拆分成的字符串数组 *@return 拆分的字符串数组的个数 */ staticint splitExpression(const std::string& strExpression,std::list<std::string>& B); }; // expression.cpp int CExpressionParser::splitExpression(conststd::string& strExpression, std::list<std::string>& B) { } ---------------------------------------------------------------------------- 在上述代码中,定义了一个表达式解析类CExpressionParser,该类提供了一个静态接口splitExpression(),用来将给定表达式字符串拆分成字符串数组,调用该接口的代码如下: 代码清单: ---------------------------------------------------------------------------- std::string strExpression; std::list<std::string> b; int count = CExpressionParser::splitExpression(str,b); ---------------------------------------------------------------------------- 那么,我们可以在类的静态成员函数内部访问类的非静态成员函数或者变量吗? 答案是:不能! 因为类的静态成员函数不属于任何一个类对象,它自然无法访问类对象的成员函数或者变量。 看到这里,大家有没有想起来我们之前提到过的单体类设计,就是采用了static关键字来提供单体访问接口?参考代码如下: 代码清单: ---------------------------------------------------------------------------- // singleobject .h classCSingleObject { public: static CSingleObject* getInstance() ; ~ CSingleObject(); private: CSingleObject(); CSingleObject(const CSingleObject &);
};
//singleobject.cpp CSingleObject * CSingleObject::getInstance() { static CSingleObject* s_pObj = new CSingleObject(); return s_pObj; } ---------------------------------------------------------------------------- 请注意,在单体类的设计中,我们把构造函数和拷贝构造函数都定义为私有的,目的就是为了防止使用者直接构造类对象。使用者只能利用我们提供的静态接口getInstance()来访问类的功能,这样就实现了单体类的设计。当然,我们这只是一个简陋版本,它并不能防止出现多线程问题,如果要做多多线程安全,还需要使用对象锁或者使用POCO等第三方库提供的线程安全的单体类模板。
结语: ---------------------------------------------------------------------------- 讲了这么多,简单总结一下,类的静态成员变量需要单独编写初始化代码。 还可以为类提供静态成员函数来实现一些与该类密切相关的功能。 可以利用static实现单体类设计。 OK,总算可以休息一下了。
---------------------------------------------------------------------------- 如果您喜欢本文欢迎转发。也可关注本人的微信公众号,或者加QQ群:C++老鸟日记交流群:870038457。 参考资料 ---------------------------------------------------------------------------- 《C++编程思想》两卷合订本中文版(10.3章节),(美) BruceEckel Chuck Allison著
|