mql5中的OOP、模板和宏,细微之处和用途 - 页 2

 
Ilya Malev:

我遇到过很多在全局初始化的类中声明静态字段的情况(在OnInit之前),只要你在类描述之后,在声明其实例的全局变量 之前重新声明静态字段,静态字段的初始化就不会有任何问题(因为在这种情况下,按照我的理解,它被认为是全局的,在类实例之前初始化)。也就是说,你只需要拒绝在方法和函数里面声明静态变量就没有问题了。

是的,这是正确的,在常规类中,它被立即初始化。但它在模板中没有被初始化。

template<typename T>
class A
{
 public: 
  static int a;
};

template<typename T>
int A::a=10;

int f() { return A<int>::a; }

int a= f();

void OnStart()
{
  Print(a); // Результат: 0
};
 
Alexey Viktorov:

你不能完全拒绝在方法和函数中声明静态变量,但至少不要用那些包含静态变量的方法或函数初始化其他静态变量。

在这个例子中,一开始静态int b变量将被初始化,但int a(int n)函数中的静态int f变量还没有被初始化,结果我们会得到胡言乱语。

顺便说一句,是的,这又是一个bug。 即除了静态/全局变量的单独初始化,代码以错误的顺序初始化静态变量 本身。所以你说 "不要用那些包含静态变量的方法或函数来 初始化其他静态变量"--你实际上是如何建议遵守这一点的? 每个函数都是独立的,都是自己存在 的。它有自己的实施方式,可能会有变化。 假设它以前没有静态变量,然后你决定添加它,这意味着某处可能会出错,因为它的设计中没有静态变量的函数。 那么你要如何控制这一切呢?

 
我不明白这种放弃这个或那个的决定。为什么要放弃? 为什么? 当你能解决这个问题,并且不否定自己的时候。 那么,每个人都有自己的选择......
 
Alexey Navoykov:

顺便说一下,是的,这是另一个bug,即除了单独初始化静态/全局重测,它还以错误的顺序初始化静态变量 本身。所以你说 "不要用那些包含静态变量的方法或函数来 初始化其他静态变量"--你实际上是如何建议遵守这一点的? 每个函数都是独立的,都是自己存在 的。它有自己的实施方式,可能会有变化。 假设它以前没有静态变量,然后你决定添加它,这意味着某处可能会出错,因为它的设计中没有静态变量的函数。 那么你要如何控制这一切呢?

这根本不是一个问题。拒绝用函数初始化变量就足够了,一切都将归于平静。

int a(int n)
{
 static int f=7;
 return(f+=n);
}

void OnTick()
{
 static int b;
 b=a(9);
}
它可以正常工作。有什么问题呢?一条线?
 
Alexey Viktorov:

它可以为呼声和呼唤而工作。有什么问题呢?一条线?

那么你是否理解这里的逻辑是不同的? 如果你在每次调用时都给它赋值,为什么还要把b声明为静态?
 
Alexey Navoykov:
那么,你是否理解这里的逻辑是不同的? 如果你在每次调用时都给它赋值,为什么要声明b是静态的?

我同意。我在匆忙中搞砸了一点。但是'b'变量可以在某些条件下被分配一个值,而不是9个值,可以根据条件传入函数。


但在你的例子中,'a'变量是否必须全局初始化?

template<typename T>
class A
{
 public: 
  static int a;
};

template<typename T>
int A::a=10;

int f() { return A<int>::a; }

int a= f();

void OnStart()
{
  Print(a); // Результат: 0
};

脚本中没有其他选项,在Expert Advisor中,你可以在全局层面声明该变量,并在OnInit()中初始化它。

了解并观察初始化顺序就足够了。首先是全局变量,然后是静态变量,最后是代码中出现的局部变量。

这个例子就违反了文档中关于不要用函数初始化变量 的建议。对开发者来说,写这样的警告比解释哪里可以、哪里不可以更容易。

从你的例子中删除静态的东西,得到你想要的结果。

 
Alexey Viktorov:

但是,你的样本中的'a'变量必须是全局初始化的吗?

不一定,但对我来说更方便。 如果它是一个常量(全局可见的常量大多被声明,如果代码很聪明的话),那么就没有其他选择。

脚本中没有其他选项,在EA中你可以 全局声明一个变量并在OnInit()中初始化它。

了解并观察 初始化顺序就足够了。首先是全局变量,然后是静态变量,最后是代码中出现的局部变量。

这个例子就违反了文档中关于不要用函数初始化变量 的建议。对开发者来说,写这样的警告比解释哪里可以、哪里不可以更容易。

从你的例子中去掉 静态的东西,就可以得到理想的结果。

关于黄色的一切,我有一个问题:为什么?我已经找到了解决这个问题的方法。
 
更新了前页的文件。纠正了一个小缺陷。
 
Alexey Navoykov:

不一定,但对我来说更方便。 如果它是一个常量(而全局可见性大多声明常量,如果代码是合格的),这里没有其他选择。

关于黄色的一切,我有一个问题:为什么?我已经找到了解决这个问题的方法。

你已经找到了一个创造它的方法。

 
Alexey Navoykov:

是的,没错,在普通类中,它被立即初始化。但在模板类中则不然。

你试图在初始化阶段使用一个类 的静态字段,而该类至少有一个实例被创建。在我看来,这是一种变态...这就是它的正常工作方式。

template<typename T>
class A
{
 public: 
  A(){}
  static int a;
  int f(){return a;}
};

template<typename T>
int A::a=10;

A<int> _a;


int a= _a.f();

void OnStart()
{
  Print(a);
};
一般来说,封装的原则表明,这种字段应该是隐藏的,而不是公开的。