MQL5中的OOP问题 - 页 83

 

呀...人们对const(((())是多么的混乱。

要理解带有const指定符的方法

class CTest{
   int i;
public:
   CTest(int _i):i(_i){}
   int Get() const {return i;}
   int Get()   {return 2*i;}
};

void OnStart()
  {
   const CTest a(5);
   CTest b(8);
   Print(a.Get()); //5
   Print(b.Get()); //16
  }

现在做

   //int Get() const {return i;}

然后反之亦然。

//   int Get()   {return 2*i;}

)))

 
Alexandr Andreev:

也是同一代码的一个变体。


这是与常数有关的。

而且你确信,输入的

Compare(CObject const *node,int const mode=0)

你会一直喂养

CChartObjectRectangleX*

不检查就写?

return (  Time(1)-dynamic_cast<const ME*>(node).Time(1));

?

 
Alexandr Andreev:

由于基类没有对输入参数的引用,所以没有宪法 的变体也能正确工作,尽管这种风格不是很聪明

这样做是行不通的。你不能改变比较中的签名。这主要是SB中包含的QuickSort方法所需要的,它可以使常规排序工作。

如果你改变签名,它就不是虚函数的覆盖,而是重载,它调用基类CObject 的方法,返回0。

当然,这可以通过对容器的包装(装饰)来解决,但为什么要做这些不必要的动作,否则就不要用SB,一切从头开始写。

 
Vladimir Simakov:

它似乎与你的相同,只是字母较少。因此,这是一个品味问题,但我删除了额外的变量(很可能,编译器会将其作为优化的一部分而删除)。

关于我的!节点检查。必须用CheckPointer(node)==POINTER_INVALID来代替, 但这是一个开销--一个函数调用。即使它是内联的,它至少也是在取消引用和检查状态标志。如果只是库或具体的,你写的程序将使用比较方法,最好!节点和代码上的无效指针。如果你懒得注意指针,或者这是一个为弱者准备的库,只有CheckPointer(node)==POINTER_INVALID。

如果你删除了你强调的const指定符,你就不能从一个常量对象 中调用这些方法。

UPD:可以删除突出显示的检查,因为它是在被调用的方法中。

Vladimir,只是在这种情况下CheckPointer是多余的。 dynamic_cast会在任何失败的cast中返回NULL,包括指针被破坏的情况。如果我说错了,请纠正我。很久以前测试过,测试时间为5秒)。

CheckPointer的工作机制(简单的说,我不太懂低级别的术语)--它通过指针寻找什么样的对象,动态的还是静态的,如果我们不能得到信息,就意味着POINTER_INVALID。这可能是在动态对象被删除的情况下,其他情况我不知道,或者上传垃圾到指针,但必须检查编译器,如果你找不到漏洞。

和dynamic_cast做同样的事情,同时检查指针是否可以被投到所需的类型,即它是否是这个类型的指针或子类的指针。

如果指针被破坏,dynamic_cast无法检测到任何东西并返回NULL。

这就是为什么我没有使用CheckPointer。但我通常在任何地方都使用这种检查,以避免受到伤害。毕竟,要在软件中找到一个错误,这是不倒的,似乎有点容易)。

而非const - 理论上我们可以有一个类似GetRatingByAnyFormula()的方法 { m_rating01=Formula01(); return m_rating01;}。

如果不立即用于排序,将相当不方便,也就是说,我们必须先计算评级,然后再调用按评级排序。或者,正如已经说过的,从头开始写你自己的SB)。

 
Aleksey Mavrin:

这不是好事。签名不能在比较中改变。这主要是为了让SB中包含的常规排序方法QuickSort发挥作用。

如果你改变了签名,就不是对虚函数的覆盖,而是重载,基类CObject 的方法将被调用,其中返回0。

当然,这可以通过对容器的包装(装饰)来解决,但为什么要做这些不必要的动作,或者不使用SB而从头开始写一切?

最正确的方法是不在µl上写字

 
Aleksey Mavrin:

Vladimir,在这种情况下,CheckPointer是多余的。 dynamic_cast将在任何不成功的投掷中返回NULL,包括指针被破坏的情况。如果我说错了,请纠正我。很久以前测试过,测试时间为5秒)。

CheckPointer的工作机制(简单的说,我不太懂低级别的术语)--它通过指针寻找什么样的对象,动态的还是静态的,如果我们不能得到信息,就意味着POINTER_INVALID。这可能是在动态对象被删除的情况下,其他情况我不知道,或者上传垃圾到指针,但必须检查编译器,如果你找不到漏洞。

和dynamic_cast做同样的事情,同时检查指针是否可以被投到所需的类型,即它是否是这个类型的指针或子类的指针。

如果指针被破坏,dynamic_cast无法检测到任何东西并返回NULL。

这就是为什么我没有使用CheckPointer。但我通常在任何地方都使用这种检查,以避免受到伤害。毕竟,要在软件中找到一个错误,这是不倒的,似乎有点容易)。

而非const - 理论上我们可以有一个类似GetRatingByAnyFormula()的方法 { m_rating01=Formula01(); return m_rating01;}。

如果不立即用于排序,将相当不方便,也就是说,我们必须先计算评级,然后再调用按评级排序。或者你可以像前面提到的那样从头开始写你自己的SB)。

  1. 比较方法被定义为公共的,这意味着任何劣势者,无论你在规范中如何努力解释,都会把一个无效的描述符推到那里。当然,如果不是图书馆,只是为了自己,你也不必如此。
  2. 我不知道CheckPointer 是如何工作的,它的工作原理是。但无论如何,它是处理器的时钟和内存访问(它很容易变成虚拟内存)。
  3. 关于带有const指定符的方法。如果你写一个库,你必须始终牢记,对象可能需要一个常量,所以在那些方法中,不改变对象的状态,因为它是可取的。虽然到目前为止,对我自己来说,我并没有真正去理会它。
  4. 编写你自己的系统,这可能是正确的决定。这只是有趣的前景,在薪酬/劳动比例上还看不到,因此也不会完成,所以只为自己的需要)。
 
Vladimir Simakov:

关于我的!节点检查。它应该被CheckPointer(node)==POINTER_INVALID取代,但这是一个开销,函数调用。

问题不在于开销,而在于破损的指针会改变程序的逻辑。 也就是说,你不但没有发现问题,反而会把它埋得更深。

CheckPointer 应该只用于调试目的,或者作为弱指针的实现。

 
Vladimir Simakov:
  1. 比较方法被定义为公共的,所以任何劣势者,无论你在规范中如何告诉他,都会把一个无效的描述符塞到那里(让我们用正确的名字称呼事物)。当然,如果不是图书馆,只是为了自己,你也不必如此。
  2. 我不知道CheckPointer是如何工作的,它的工作原理是。但无论如何,它是处理器的时钟和内存访问(它很容易变成虚拟内存)。
  3. 关于带有const指定符的方法。如果你写一个库,你必须始终牢记,对象可能需要一个常量,所以在那些方法中,不改变对象的状态,因为它是可取的。不过到目前为止,就我自己而言,我并没有真正去理会它。
  4. 编写你自己的系统,这可能是正确的决定。这只是有趣的前景,在薪酬/劳动比例上还看不到,因此也不会有什么定论,所以只是为了自己的需要)。

1.没有争论,但我要说的是,你不需要CheckPointer(即使是对下家),因为 dynamic_cast不能返回一个非无效的指针,只能返回NULL

2.这甚至很有趣,但我不能马上想到一个例子,除了在工作时直接杀死动态对象或 "弄脏 "内存之外,还可以得到一个非无效的指针。

我想还是有这样的方法,但它们很可能都在绕过编译器检查的平面上。

3,4 同意。

P.S.

我一定是看错了1-st。测试结果显示,情况恰恰相反。这一定只是一种印象)。

void OnStart()
  {
      CChartObjectRectangle *base = new CChartObjectRectangle();
      CChartObjectRectangleX *rect = new CChartObjectRectangleX();
       CChartObjectRectangle * dbase  ;
      const CChartObjectRectangleX *drect  ;
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));
      dbase=dynamic_cast< CChartObjectRectangle *>  (base);
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL, " check? ",!dbase," broken? ", EnumToString( CheckPointer(dbase) ));
      delete base;
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));
      dbase=dynamic_cast< CChartObjectRectangle *>  (base);   
      Print("dbase= ",dbase, " NULL ? ",dbase==NULL," check? ",!dbase, " broken? ", EnumToString( CheckPointer(dbase) ));   
  }
 
是否可以在公有类部分声明一个静态数组 并在构造函数中初始化它?(如下图)(或只按元素计算?)
 bool Mass[5] = { false, true, false, true, true };
 
Pavel Verveyko:
静态数组 可以在公有类部分声明并在构造函数中初始化吗?(如下图)(或仅逐个元素?)

你可以初始化一个本地数组并执行ArrayCopy到相应的数组字段。

class A{
public:
   bool Mass[5];
   A(){
       bool mass_init[5] = { false, true, false, true, true };
       ArrayCopy(Mass, mass_init);
   }
};