通用类库 - 错误、说明、问题、使用功能和建议 - 页 21

 
fxsaber:

我们只需要为所需类型重载GetHashCode,而不是启动IEqualityComparable。

在这种情况下,两端是非常遥远的,可能的错误会出现在库的某个深处。 然后猜测为什么找不到某些函数,这是谁的错。 而接口事先保证所有需要的函数已经在对象中定义。

 
阿列克谢-纳沃伊科夫

在这种情况下,两端走得很远,可能的错误发生在库的某个深处。 然后猜测为什么找不到某个函数,是谁的错。 而接口事先保证所有必要的函数都已经在对象中定义。

你能为MqlTick 展示一个例子吗?

 
阿列克谢-纳沃伊科夫

而接口提前确保所有必要的功能都已经在对象中定义。

是的,除了这些类声称是通用的,必须对所有类型的人开箱即用。

 
fxsaber:

你能为MqlTick 展示一个例子吗?

class CMqlTick : public IEqualityComparable<CMqlTick*>
{
 public: 
   MqlTick _tick;
   bool    Equals(CMqlTick* obj) { return obj!=NULL && obj._tick.time==_tick.time; }
   int     HashCode(void)        { return _tick.time; }
};
当然还有必须投入的费用,加上指针检查。
 
阿列克谢-纳沃伊科夫
当然,这里有成本,我们要把它放到类加指针的检查中。

谢谢你,但我看不出这种方法在实践中有什么优势?

在SB中,代码是这样的

//+------------------------------------------------------------------+
//| Class CKeyValuePair<TKey, TValue>.                               |
//| Usage: Defines a key/value pair that can be set or retrieved.    |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CKeyValuePair: public IComparable<CKeyValuePair<TKey,TValue>*>
  {
protected:
   TKey              m_key;
   TValue            m_value;

public:
                     CKeyValuePair(void)                                              {   }
                     CKeyValuePair(TKey key,TValue value): m_key(key), m_value(value) {   }
                    ~CKeyValuePair(void)                                              {   }
   //--- methods to access protected data
   TKey              Key(void)           { return(m_key);   }
   void              Key(TKey key)       { m_key=key;       }
   TValue            Value(void)         { return(m_value); }
   void              Value(TValue value) { m_value=value;   }
   //--- method to create clone of current instance
   CKeyValuePair<TKey,TValue>*Clone(void) { return new CKeyValuePair<TKey,TValue>(m_key,m_value); }
   //--- method to compare keys
   int               Compare(CKeyValuePair<TKey,TValue>*pair) { return ::Compare(m_key,pair.m_key); }
   //--- method for determining equality
   bool              Equals(CKeyValuePair<TKey,TValue>*pair) { return ::Equals(m_key,pair.m_key); }
   //--- method to calculate hash code   
   int               HashCode(void) { return ::GetHashCode(m_key); }

事实证明,提议的舞蹈只是为了避免重载这个GetHashCode。但在这种情况下,是否值得这样做?

 
fxsaber:

谢谢你,但我看不出这种方法在实践中有什么优势?

在SB中,代码是这样的

事实证明,提议的舞蹈只是为了避免重载这个GetHashCode。但在这种情况下,是否值得这样做?

如果速度是关键,你最好超载。

关键是在.NET中,这个库是从那里移植过来的,所有的内置类型从一开始就已经有了接口。 这就是int,又称Int32,是如何定义的。

public struct Int32 : IComparable, IFormattable, IConvertible, 
        IComparable<int>, IEquatable<int>

这就是为什么那里没有超载。

而CKeyValuePair类本身的声明方式会有些不同。

虽然把这些时间花在改善语言的功能 上会更好。 然后整个.Net库就可以被复制,一切都会正常。

 
阿列克谢-纳沃伊科夫
当然,这里有成本,你必须把一个类,加上指针检查。
把这段代码放在GetHashCode重载里有什么问题? 那么你就不需要继承接口了
 
组合器
把这段代码塞进GetHashCode重载有什么问题?

当然,这是有可能的。但这使得控制过程变得更加困难。假设你有一堆不同的GetHashCodes,分散在整个代码中,其中哪些被调用(以及它们的位置),可能很难理解。 例如,当调用一个函数 时,参数被转换为其他类型。 在C#中,这可能是为什么模板的可能性与C++相比非常有限的原因

 
阿列克谢-纳沃伊科夫

当然,这是有可能的。但它使过程控制复杂化。

在C++中,这个接口是不必要的,正常的交互是通过<操作符的简单重载来实现的,而且这个操作符可以在CLASS之外定义。

我认为这比转这种结构要容易得多,也简洁得多。 但你需要本地支持在类外重载操作符<。

但是对于嵌入式结构来说,除了重载GetHashCode之外,没有任何东西,因为存根是可怕的,而继承是不可能的。 从结构中继承是一个拐杖式的解决方案,因为它迫使使用标准函数来手动投递结构到用户继承中,以使一切按计划进行。
 
组合器

从结构中继承是一个拐杖式的解决方案,因为它迫使你在使用标准函数时,手动将结构投给一个自定义的继承者,以使一切都按原定计划运行。

显然,你指的不是继承,而是从一个类上包裹一个结构?

实际上,这种 "强迫 "也是MQL功能的一个缺点,因为没有办法重载cast操作符,否则类很容易被隐含地cast到结构。

但是没有人理会......发展已经停滞了2年,没有改进和创新。

虽然开发人员自己在这里抱怨缺乏多种界面和其他功能,但继续吃仙人掌)。