跳至内容

Static Members of a Class

类的静态成员/结构成员

静态成员

可以使用存储类修饰符static来声明类的成员。这些数据成员由该类的所有实例共享,并存储在一个地方。非静态数据成员是为每个类对象变量创建的。

如果不声明类的静态成员,就需要将这些数据声明在程序的全局级别。这会破坏数据与类之间的关系,不符合面向对象编程的基本范式——将数据和处理数据的方法结合到类中。静态成员允许不特定于某个实例的类数据存在于类范围内。

由于静态类成员不依赖于特定实例,对其的引用如下:

class_name::variable

其中class_name是类的名称,variable是类成员的名称。

如你所见,要访问类的静态成员,需要使用上下文解析运算符 ::。当在类方法内访问静态成员时,上下文运算符是可选的。

类的静态成员必须显式初始化所需的值。为此,必须在全局范围内声明并初始化它。静态成员初始化的顺序将对应于它们在全局范围内的声明顺序。

例如,我们有一个用于解析文本的CParser类,我们需要计算处理过的单词和字符的总数。我们只需要将必要的类成员声明为静态并在全局级别初始化它们。然后,类的所有实例都将使用共同的单词和字符计数器。

//+------------------------------------------------------------------+
//| Class "Text analyzer"                                            |
//+------------------------------------------------------------------+
class CParser
  {
public:
   static int        s_words;
   static int        s_symbols;
   //--- Constructor and destructor
                     CParser(void);
                    ~CParser(void){};
  };
...
//--- Initialization of static members of the Parser class at the global level
int CParser::s_words=0;
int CParser::s_symbols=0;

可以使用const关键字声明静态类成员。这样的静态常量必须用const关键字在全局级别初始化:

//+------------------------------------------------------------------+
//| Class "Stack" for storing processed data                         |
//+------------------------------------------------------------------+
class CStack
  {
public:
                     CStack(void);
                    ~CStack(void){};
...
private:
   static const int  s_max_length; // Maximum stack capacity
  };

//--- Initialization of the static constant of the CStack class
const int CStack::s_max_length=1000;

指针this

关键字this表示隐式声明的指向自身的指针——指向类的特定实例,在该实例的上下文中执行方法。它只能用于类的非静态方法。指针this是任何类的隐式非静态成员。

在静态函数中,只能访问类的静态成员/方法。

静态方法

在MQL4中可以使用static类型的成员函数。静态修饰符必须位于类内部声明中的函数返回类型之前。

class CStack
  {
public:
   //--- Constructor and destructor
                     CStack(void){};
                    ~CStack(void){};
   //--- Maximum stack capacity
   static int        Capacity();
private:
   int               m_length;     // The number of elements in the stack
   static const int  s_max_length; // Maximum stack capacity
  };
//+------------------------------------------------------------------+
//| Returns the maximum number of elements to store in the stack     |
//+------------------------------------------------------------------+
int CStack::Capacity(void)
  {
   return(s_max_length);
  }
//--- Initialization of the static constant of the CStack class
const int CStack::s_max_length=1000;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- declare CStack type variable
   CStack stack;
//--- call the object's static method
   Print("CStack.s_max_length=",stack.Capacity());
//--- it can also be called the following way, as the method is static and does not require the presence of the object
   Print("CStack.s_max_length=",CStack::Capacity());
  }

带有const修饰符的方法称为常量方法,不能修改其类的隐式成员。类常量函数的声明和常量参数的声明称为const正确性控制。通过这种控制,可以确保编译器会确保对象值的一致性,并在编译时出现错误时返回错误。

const修饰符放在类声明中的参数列表之后。类外部的定义也应包含const修饰符:

//+------------------------------------------------------------------+
//| Class "Rectangle"                                                |
//+------------------------------------------------------------------+
class CRectangle
  {
private:
   double            m_width;      // Width
   double            m_height;     // Height
public:
   //--- Constructors and destructor
                     CRectangle(void):m_width(0),m_height(0){};
                     CRectangle(const double w,const double h):m_width(w),m_height(h){};
                    ~CRectangle(void){};
   //--- Calculating the area
   double            Square(void) const;
   static double     Square(const double w,const double h);// { return(w*h); }
  };
//+------------------------------------------------------------------+
//| Returns the area of the "Rectangle" object                       |
//+------------------------------------------------------------------+
double CRectangle::Square(void) const
  {
   return(Square(m_width,m_height));
  }
//+------------------------------------------------------------------+
//| Returns the product of two variables                             |
//+------------------------------------------------------------------+
static double CRectangle::Square(const double w,const double h)
  {
   return(w*h);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Create a rectangle rect with the sides equal to 5 and 6
   CRectangle rect(5,6);
//--- Find the rectangle area using a constant method
   PrintFormat("rect.Square()=%.2f",rect.Square());
//--- Find the product of numbers using the static method of class CRectangle
   PrintFormat("CRectangle::Square(2.0,1.5)=%f",CRectangle::Square(2.0,1.5));
  }

使用const正确性控制的另一个优点是,在这种情况下,编译器会生成特殊的优化,例如将常量对象放入只读内存中。

静态函数不能使用const修饰符,因为该修饰符确保调用此函数时实例成员的值保持不变。但是,如上所述,静态函数无法访问非静态类成员。

另请参阅

静态变量变量引用。修饰符和关键字this

最后更新于