关于OOP(面向对象的编程)的问题 - 页 6

 
C-4:
在需要动态类型识别的复杂对象转换中,指针是不可缺少的。

瓦西里,请举个例子!

我只知道有一种情况,你需要分配内存并需要一个指针。

我相信你几乎总是可以不用它。最好不要使用手动内存管理。总有一个标准库 已经在处理这些问题。

 
Integer:


有一条原则在任何地方都适用:每件事都必须尽可能简单地完成。你不需要为了进入事情的漩涡而进入事情的漩涡。如果一个问题可以简单解决,就应该简单解决。


正是如此。而这正是正确设计班级的重要之处。而要做到这一点,重要的是要预测下一个阶层(后裔)会是什么。

通常情况下,基类应该有最低限度的功能,但最好是创建大量的虚拟方法,以设定类的使用矢量。

在MQL的情况下--可能正好相反--基类中有更多的功能,就像在VOLDEMAR 中。但是没有狂热。


有贸易符号属性(POINT、STOPLEVEL等)。MODE_XXX 用于MarketInfo())。我们最好把它们塞进cSymbol 类,比如说。


有订单属性(开盘价、类型、手数等)。OrderXXX())。例如,把它们放到一个单独的cOrder 类中会更好。

如果我们记得订单可以分部分关闭,那么我们也应该把BaseLot 字段分配给该类(以便知道哪一部分已经关闭),以此类推。


有(对我来说)一个时间表--指定的时间段(按天计算),我们可以开仓和平仓,只平仓的时间段(如果已经盈亏平衡,则追踪),还有一个时间段,我们完全不工作,然后关闭所有开仓和删除未开仓订单。

请记住关于差距,在许多(如果不是全部)经纪公司的最后一个小时的交易中,可能会改变交易条件,许多经纪公司在每个交易日都有一个交易金属的休息时间。


最后,还有一个EA--一个特定的算法,在特定的时间表上,用特定的 "其 "订单列表和自己的数据进行计算,对特定的符号工作。

我们可以创建一个cExpert 类,它将包含一个cSymbol 类的对象 一个cOrder 类的对象阵列。这个基本的cExpert 将包含更新cOrder 对象属性的功能,订单处理的功能,错误处理,统计等。

我个人认为,以AccountFreeMargin() 的%计算手数,为每个订单生成一个独特的magik(更容易把反向订单放到一个特定的订单上),下反向订单的功能,等等,都很有用。

而这正是cExpert 可以降生的地方,独特的附加数据集和功能将决定在市场上做什么(开仓/公司/平仓订单)。

即实施交易策略。而这将是我们所说的 "XXX战略EA"。


所有的 基本功能 都在基础的cExpert 类中。子类将包含交易策略的算法。

好吧,也许有人会在交易中加入一些高级错误处理或高级统计(如果没有源代码,而且不能塞进基本的cExpert)。

请注意,我们正在花时间,创建一个将简化编写EA的类。事实上,它是一个专家顾问模板。结构上完整,没有刷子(所有必要的数据与代码放在一起)。


至于所谓的包装函数比openorders() "多余 "的问题,我个人只是支持这样的包装函数(尤其是--如果它们有额外的功能,而不仅仅是调用基本函数)。

例如,如果在调用包装器时,SL和 TP 是以点为单位指定的,我们必须将它们转换为绝对数字,而且还要根据顺序类型进行加减(尽管在这种情况下,这种转换也可以放在operorders()中)。

我个人认为,理解调用BuyStop(...) 的代码并检查一次BuyStop() 是否做得正确,比每次解析OrderSend() 参数的正确性要容易。

PS:这是一个很大的工作,包括在周末。感谢Pavlick和 mql5 提供的示例代码。

看看这些例子,想一想,真的有必要在编程任务领域创建一个类的层次结构吗,这是用MQL写的?

你真的需要在一个基本的基础上有一整个系列的课程吗(所有这些 "三角形"、"正方形 "等等)?

再一次引用Integer 的金句:不要为了 进入灌木丛而进入灌木丛。

哦,要么是我没注意到,要么是最近出现了带例子的文档 部分。

 
Zhunko:

我只知道有一种情况,你需要分配内存并需要一个指针。

我相信你几乎总是可以不用它。建议不要使用手动内存管理。总有一个标准库已经解决了这些问题。


这里可能是它的全部内容。


我们假设有一个cFather 类,它有 int GetData() 方法,返回3。还有方法 PrintData(),它输出从GetData() 得到的东西。

它的后代cChild 已经重写了GetData(),现在返回5。

如果我们声明一个cFather 类型的对象为TestObject,那么TestObject.GetData()将总是返回3。

如果我们声明cFather* TestObject=new cChild1,那么TestObject.GetData()将返回5,尽管它看起来是cFather。

需要这样做,以便现在编写的代码可以在cFather 类的任何后裔上调用GetData() 方法,即使它(后裔类)还不存在。

也就是说,如果这时出现了cChild2 类,用它的GetData() 将返回7,那么在cFather* Test2=new cChild2 函数Test2.PrintData() 后将开始输出7。

如果有一些函数期望一个 "对cFather 类对象的引用 "的参数并使用它GetData(),它将获得任何 cFather 后代的正确数据。

方法绑定发生在调用new 的时候。如果它没有被引用,那么绑定将是硬性的,也就是说,声明的类的方法将被调用。

见这里这里

 
EverAlex:

这似乎是它的全部内容。

...

有一个":: "操作符,允许你访问整个基类派生类 链中的任何方法,而无需分配内存或指针。
 
C-4:


你的课90%都是多余的。只有两个函数做主要工作,这两个函数是openorders tip 为什么你用Sel、Buy SelStop等,而事实上它们都只是调用Openorders?此外,订单类型是以int形式传递的,所以它不受保护。你最好使用你自己的枚举或标准的ENUM_ORDER_TYPE来代替int。而且一般来说,你最好永远不要使用神奇的数字 "1"、"2 "等,只使用枚举。这将防止你向函数发送左边的订单值。开放边界函数本身太大。很明显,它由两个部分组成,即进行交易的部分和检查条件的部分。每一个都应该是一个独立的私人职能。

这是一个良好的开端,但我们仍有很多东西需要学习。提示函数最好改写如下。

在调用该方法时,我可以直观地看到我下的是什么类型的订单,这很方便...

关于比较,请详细描述为什么不建议用0来比较双数?

 
C-4:
在需要动态类型识别的复杂对象转换中,指针是不可缺少的。

动态类型识别的存在通常表明一个项目的 拐杖结构。
 
如果在EA中全局地声明一个类(Class c;),那么在一次打勾时改变的内部类对象 的状态会在下一次打勾时保存吗?
 
EverAlex:

这似乎就是它的意义所在。


假设有一个cFather 类,它有 int GetData()方法,返回3。还有方法 PrintData(),它输出从GetData() 得到的东西。

还有它的后代cChild,它已经重写了GetData(),现在返回5。

如果我们声明一个cFather 类型的对象为TestObject,那么TestObject.GetData()将总是返回3。

如果我们声明cFather* TestObject=new cChild1,那么TestObject.GetData()将返回5,尽管它看起来是cFather。

需要这样做,以便现在编写的代码可以在cFather 类的任何后裔上调用GetData() 方法,即使它(后裔类)还不存在。

也就是说,如果这时出现了cChild2 类,用它的GetData() 将返回7,那么在cFather* Test2=new cChild2 函数Test2.PrintData() 后将开始输出7。

如果有一些函数期望一个 "对cFather 类对象的引用 "的参数并使用它GetData(),它将获得任何 cFather 后代的正确数据。

方法绑定发生在调用new 的时候。如果它没有被引用,那么绑定将是硬性的,也就是说,声明的类的方法将被调用。

见这里这里

class cFather
{
public:
    int GetData() {return 3;}
};

class cChild : public cFather
{
public:
    int GetData() {return 5;}
};
    
int f(cFather *p) {return p->GetData();}
    
int main()
{
    cChild obj;
    f(&obj);                // вернет 3
    obj.cFather::GetData(); // вернет 3
    
    return 0;
}
 
Pavlick:


也许我写的这个例子是白写的。它在MKL中不起作用。

cChild obj;
f(&obj);                // вернет 3
obj.cFather::GetData(); // вернет 3

H.k.,不是指点江山,而是笑里藏刀。

P.S:用dlls写,有机会学习正常的语言。

 
Pavlick:


也许我写的这个例子是白写的。它在MKL中不起作用。

H.k.,不是指点江山,而是笑里藏刀。

P.S:用dlls写,有机会学习正常的语言。


class cFather
  {
public:
   int GetData() {return 3;}
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class cChild : public cFather
  {
public:
   int GetData() {return 5;}
  };

int f(cFather *p) {return p.GetData();}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnStart()
  {
   cChild obj,*ptr=GetPointer(obj);
   f(ptr);                     // вернет 3
   ((cFather *)ptr).GetData(); // вернет 3

   return 0;
  }