mql5中的OOP、模板和宏,细微之处和用途 - 页 10 1...34567891011121314151617...28 新评论 Ilya Malev 2019.01.25 20:41 #91 Alexey Navoykov:毕竟,继承链可以是你想要的任何东西:甚至是Interface<CBase>,甚至是Interface<C<B<A<CBase>>>>,有大量的变体。我们将不得不把CBase依次投给所有可能的变体,这是不现实的。 我记得我打算实现在类对象 本身中存储接口的信息,除了现有的接口垫之外,还要制作独立的接口类,作为我们的垫的包装。但后来我得出结论,所有这些都是不必要的,是多余的。在实践中,我从未见过需要将基类投给任何接口的情况,这没有任何意义。 唯一的选择是找出该类是否支持这个接口,以达到调试的目的,但我们不需要为此而投。在我看来,我们应该将接口存储在接口中。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 我在那里勾画了一些代码作为例子,但我真的不想用太多的字母把论坛弄得一团糟。 Artyom Trishkin 2019.01.25 20:43 #92 Ilya Malev:在我看来,接口应该存储在接口本身。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 我在那里勾画了一些代码作为例子,但我真的不想用太多的字母把论坛弄得一团糟。来吧,发布它。总之,这不是垃圾,而是一个讨论的主题。但在那个讨论被转移到这里的主题中,这将是不恰当的。 Ilya Malev 2019.01.25 20:44 #93 好的) //+------------------------------------------------------------------+ //| Comparer demo | //| Copyright 2012, CompanyName | //| http://www.companyname.net | //+------------------------------------------------------------------+ #property strict #define throw(M) {int a=0,b=1; printf("%s: %s",__FUNCSIG__,M); Print(b%a); } #define msg_pure "Method not implemented!" #define msg_compare "Types are uncomparable!" template<typename T,typename CBase> class IComparer; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Number { public: virtual int CompareTo(Number *par) { throw(msg_pure); return 0; } int operator==(Number*par) { return CompareTo(par); } template<typename T> T *operator[](T*) { return dynamic_cast<T*>(&this); } virtual string ToStr() { return StringFormat("Type %s, object %i (%i)",typename(this),&this,CheckPointer(&this)); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Int: public Number { private: int i; public: int Get() { return i; } Int*Set(int p) { i=p; return &this; } virtual int CompareTo(Number*par) { Int*v1=dynamic_cast<Int*>(par); if(v1) { return IComparer<Int,Int>::GetComparer()[ IComparer<Int,Int>::GetComparer() ].Compare( &this,v1 ); } Double*v2=dynamic_cast<Double*>(par); if(v2) { return IComparer<Double,Int>::GetComparer()[ IComparer<Double,Int>::GetComparer() ].Compare( &this,v2 ); } throw(msg_compare); return 0; } Int*operator=( int p ) { return Set( p ); } virtual string ToStr() { return IntegerToString(i); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class Double: public Number { private: double f; public: double Get() { return f; } Double*Set(double p) { f=p; return &this; } virtual int CompareTo(Number*par) { Double*v1=dynamic_cast<Double*>(par); if(v1) { return IComparer<Double,Double>::GetComparer()[ IComparer<Double,Double>::GetComparer() ].Compare( &this,v1 ); } Int*v2=dynamic_cast<Int*>(par); if(v2) { return IComparer<Int,Double>::GetComparer()[ IComparer<Int,Double>::GetComparer() ].Compare( &this,v2 ); } throw(msg_compare); return 0; } Double*operator=(double p) { return Set(p); } virtual string ToStr() { return DoubleToString(f,_Digits); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template<typename T,typename CBase> class IComparer: public CBase { private: static IComparer *comparer; public: IComparer() { if(!comparer) { comparer=&this; } } virtual int Compare(CBase &op1,T &op2) { throw(msg_pure); return 0; } static IComparer *GetComparer() { return comparer ? comparer : new IComparer; } static string ToStr(int cmp) { return(!cmp?"equal":(cmp==-1?"lesser than":(cmp==1?"greater than":"undefined"))); } }; template<typename T,typename CBase> IComparer *IComparer::comparer=NULL; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpIntToInt: public IComparer<Int,Int> { virtual int Compare(Int &op1,Int &op2) { return(op1.Get()>op2.Get())-(op1.Get()<op2.Get()); } } citi; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpIntToDouble: public IComparer<Int,Double> { virtual int Compare(Double &op1,Int &op2) { return int(op1.Get()-op2.Get()>DBL_EPSILON)-int(op2.Get()-op1.Get()>DBL_EPSILON); } } citd; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpDoubleToInt: public IComparer<Double,Int> { virtual int Compare(Int &op1,Double &op2) { return int(op1.Get()-op2.Get()>DBL_EPSILON)-int(op2.Get()-op1.Get()>DBL_EPSILON); } } cdti; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CmpDoubleToDouble: public IComparer<Double,Double> { virtual int Compare(Double &op1,Double &op2) { return int(op1.Get()-op2.Get()>DBL_EPSILON)-int(op2.Get()-op1.Get()>DBL_EPSILON); } } cdtd; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnStart() { srand(GetTickCount()); Number *n[10]; for(int i=0;i<10;i++) { if(rand()%2==0) n[i]=new Int=rand(); else n[i]=new Double=rand()*rand()/(1.0*rand()); } for(int i=0;i<10;i++) { int a=rand()%10,b=rand()%10; printf("%s is %s %s",n[a].ToStr(),IComparer<Int,Int>::ToStr(*n[a]==n[b]),n[b].ToStr()); } for(int i=0;i<10;i++) { delete n[i]; } } //+------------------------------------------------------------------+ Alexey Navoykov 2019.01.25 21:20 #94 Ilya Malev:好的) 如果两个参数都是T,为什么IComparer::Compare(CBase &op1, T &op2) 方法会在那里? Ilya Malev 2019.01.25 21:22 #95 Alexey Navoykov:如果两个参数都是T,为什么还有IComparer::Compare(CBase &op1, T &op2) 方法?是否只能比较相同的类型?我的假设是,它不是。使T==CBase,将有两个参数T ) Alexey Navoykov 2019.01.25 21:27 #96 啊,明白了,那你就错了。 在你的例子中,IComparer类应该像IComparer<T1,T2,CBase>。 相应地,方法也会如此。 virtual Compare(T1 &op1, T2 &op2) = 0; 当你继承这个类的时候,你将恰好重载这个方法,一切都将归位。 Ilya Malev 2019.01.25 21:28 #97 Alexey Navoykov:啊,我明白了,你完全搞错了。 IComparer类在你的例子中应该是IComparer<T1,T2,CBase>。 而当你继承一个类时,你将重载这个方法,一切都将归位。那么这个CBase的含义是什么呢?还有,为什么正好有2个同一类型的值必须进行比较? Ilya Malev 2019.01.25 21:31 #98 我的目标不是让它和C#完全一样,而且,我还没有详细了解它是怎么做的。但一眼看去,两个函数的IEnumerator的reset和next是非常不方便的,我肯定不会在同一个表格中复制它 ) TheXpert 2019.01.25 21:34 #99 你是疯了吗? 一个纯虚拟函数 是这样写的--虚拟 int CompareTo(Number *par) = 0 。 被诅咒的是编译器,而不是自写的异常代理。 Ilya Malev 2019.01.25 21:36 #100 TheXpert:一个纯虚拟函数 是这样写的--虚拟 int CompareTo(Number *par) = 0。 编译器将被诅咒,而不是自写的异常代理。我不需要编译器发誓,因为我不断地操作基本类型的类(本例中的Number)。如果编译器对它发誓,代码根本不会运行 1...34567891011121314151617...28 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
毕竟,继承链可以是你想要的任何东西:甚至是Interface<CBase>,甚至是Interface<C<B<A<CBase>>>>,有大量的变体。我们将不得不把CBase依次投给所有可能的变体,这是不现实的。
我记得我打算实现在类对象 本身中存储接口的信息,除了现有的接口垫之外,还要制作独立的接口类,作为我们的垫的包装。但后来我得出结论,所有这些都是不必要的,是多余的。在实践中,我从未见过需要将基类投给任何接口的情况,这没有任何意义。 唯一的选择是找出该类是否支持这个接口,以达到调试的目的,但我们不需要为此而投。
在我看来,我们应该将接口存储在接口中。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 我在那里勾画了一些代码作为例子,但我真的不想用太多的字母把论坛弄得一团糟。
在我看来,接口应该存储在接口本身。Interface<T,CBase>::GetComparer().Compare(CBase &a, T& b); 我在那里勾画了一些代码作为例子,但我真的不想用太多的字母把论坛弄得一团糟。
来吧,发布它。总之,这不是垃圾,而是一个讨论的主题。但在那个讨论被转移到这里的主题中,这将是不恰当的。
好的)
好的)
如果两个参数都是T,为什么IComparer::Compare(CBase &op1, T &op2) 方法会在那里?
如果两个参数都是T,为什么还有IComparer::Compare(CBase &op1, T &op2) 方法?
是否只能比较相同的类型?我的假设是,它不是。使T==CBase,将有两个参数T )
啊,明白了,那你就错了。 在你的例子中,IComparer类应该像IComparer<T1,T2,CBase>。 相应地,方法也会如此。
当你继承这个类的时候,你将恰好重载这个方法,一切都将归位。啊,我明白了,你完全搞错了。 IComparer类在你的例子中应该是IComparer<T1,T2,CBase>。
而当你继承一个类时,你将重载这个方法,一切都将归位。那么这个CBase的含义是什么呢?还有,为什么正好有2个同一类型的值必须进行比较?
你是疯了吗?
一个纯虚拟函数 是这样写的--虚拟 int CompareTo(Number *par) = 0 。
被诅咒的是编译器,而不是自写的异常代理。
一个纯虚拟函数 是这样写的--虚拟 int CompareTo(Number *par) = 0。
编译器将被诅咒,而不是自写的异常代理。
我不需要编译器发誓,因为我不断地操作基本类型的类(本例中的Number)。如果编译器对它发誓,代码根本不会运行