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修饰符,因为该修饰符确保调用此函数时实例成员的值保持不变。但是,如上所述,静态函数无法访问非静态类成员。