고문 프로젝트 - 페이지 5

 

George Merts
Стандартный CObject - это "объект списка или сортированного массива". CMyObject - это CObject, имеющий определенный тип, и содержащий некоторое значение, данное при его создании. Этот объект мне понадобился всвязи с повсеместным приведением объектов к базовому абстрактному классу - чтобы понимать по указателю, на какой именно объект "на самом деле" указывает. Тип CMyObject - устанавливается как раз той самой функцией SetMyObjectType(). Эта функция в обязательном порядке вызывается в конструкторах любых наследников от CMyObject, чтобы назначить идентификатор класса, к которому принадлежит создаваемый объект.

생성자가 열려 있고 매개변수화 되지 않았습니다 .

 class CTradeHistoryI: public CMyObject
{
public :
   void CTradeHistoryI() {    SetMyObjectType( MOT_TRADE_HISTORY_I ); };
}

이것은 후임자가 해당 유형을 설정할 수도 있고 설정하지 않을 수도 있음을 의미합니다. 저것들. 후임자 내부에서 SetMyObjectType 메서드를 호출하는 것을 잊어버린 경우 - 쓰기가 낭비됩니다.

무엇을 할 수 있습니까?

1. 외부 생성에서 생성자를 닫습니다.

 class CTradeHistoryI: public CMyObject
{
protected :
   void CTradeHistoryI() {    SetMyObjectType(MOT_TRADE_HISTORY_I); };
}

그러면 CTradeHistoryI의 후손만 인스턴스를 생성할 수 있으므로 MOT_TRADE_HISTORY_I 유형에 대한 필요성이 사라집니다. MOT_TRADE_HISTORY_I 유형은 실제로 존재하지 않습니다. CTradeHistoryI는 인터페이스이며 이 유형으로 인스턴스화할 수 없습니다. 저것들. 생성자를 닫음으로써 존재하지 않는 유형에 대한 설명 이라는 모순을 해결합니다.

2. 인스턴스화 순간에 명시적 입력에 대한 요구 사항을 설정합니다.

 enum ENUM_OBJ_TYPE
{
   OBJ_HIST_DEALS_LIST,
   OBJ_HIST_ORDERS_LIST
   ...
};

class CTradeHistoryI: public CMyObject
{
private :
   ENUM_OBJ_TYPE   m_obj_type;
protected :
   CTradeHistoryI(ENUM_OBJ_TYPE obj_type)
   {
      m_obj_type = obj_type;
   }
public :
   ENUM_OBJ_TYPE ObjectType ( void ) const
   {
       return m_obj_type;
   }
};

class CTradeHistory : public CTradeHistoryI
{
public :
   CTradeHistory( void );
};

CTradeHistory::CTradeHistory( void ) : CTradeHistory(OBJ_HIST_DEALS_LIST)
{
}

이제 명시적인 유형 할당 없이 자식을 만들 수 없습니다.

 
Vasiliy Sokolov :

표준적이고 이해할 수 있는 CObject가 있는데 왜 CMyObject의 형태로 바퀴를 재발명합니까?

MQL의 CObject에서 어떤 장점을 발견했는지 모르겠습니다. 각 개체에 채워진 두 개의 불필요한 포인터 = 16바이트 손실 + 메모리를 할당 하고 이러한 포인터를 초기화할 때 추가 오버헤드. OOP 자체가 성능을 저하시키고 그런 어리석은 결정이 있으면 ...
 
Alexey Navoykov :
MQL의 CObject에서 어떤 장점을 발견했는지 모르겠습니다. 각 개체에 채워진 두 개의 불필요한 포인터 = 16바이트 손실 + 메모리를 할당 하고 이러한 포인터를 초기화할 때 추가 오버헤드. OOP 자체가 성능을 저하시키고 그런 어리석은 결정이 있으면 ...

먼저 OOP를 배운 다음 토론하겠습니다. m_prev, m_next 초기화는 일반적으로 발생하지 않는 경우입니다.

 
Vasiliy Sokolov :

먼저 OOP를 배운 다음 토론하겠습니다. m_prev, m_next 초기화는 일반적으로 발생하지 않는 경우입니다.

당신 뒤에 만.

따라서 정보를 위해 MQL에서 포인터 초기화가 항상 수행됩니다.

 
Vasiliy Sokolov :

생성자가 열려 있고 매개변수화 되지 않았습니다 .

이것은 후임자가 해당 유형을 설정할 수도 있고 설정하지 않을 수도 있음을 의미합니다. 저것들. 후임자 내부에서 SetMyObjectType 메서드를 호출하는 것을 잊어버린 경우 - 쓰기가 낭비됩니다.

무엇을 할 수 있습니까?

...

예, 실제로 SetMyObjectType()을 지정하는 것을 잊어버린 경우도 있습니다. 개체는 기본 CMyObject 유형으로 생성됩니다.

그리고 솔루션이 좋습니다.

제안이 수락됩니다.

그러나 나는 보호된 생성자를 좋아하지 않습니다.

 
George Merts :

예, 실제로 SetMyObjectType()을 지정하는 것을 잊어버린 경우도 있습니다. 개체는 기본 CMyObject 유형으로 생성됩니다.

그리고 솔루션이 좋습니다.

제안이 수락됩니다.

그러나 나는 보호된 생성자를 좋아하지 않습니다.

보호된 생성자는 그러한 생성자가 있는 부모로부터 직접 상속하는 클래스의 삶을 더 어렵게 만듭니다. 그러나 사용자 수준에서는 생각하지 않고 자유롭게 파생 개체를 만들 수 있습니다.

따라서 불편을 겪지 않아야 합니다.

MQL에는 다른 옵션이 없습니다. 형 제어 시스템이 없거나 오히려 존재하지만 저개발 형태이므로 생성자를 숨겨서 형을 보호해야 합니다.

 
Alexey Navoykov :
MQL의 CObject에서 어떤 장점을 발견했는지 모르겠습니다. 각 개체에 채워진 두 개의 불필요한 포인터 = 16바이트 손실 + 메모리를 할당 하고 이러한 포인터를 초기화할 때 추가 오버헤드. OOP 자체가 성능을 저하시키고 그런 어리석은 결정이 있으면 ...

왜 "바보"? 제 생각에 오버헤드는 매우 작으며 CObject가 목록과 정렬된 배열을 구성하기 위해 제공하는 편리함을 분명히 가치가 있습니다.

마이크로초와 바이트를 추적해야 하는 경우 물론 이러한 "손실된 바이트"가 너무 많은 리소스를 설명하는지 파악하는 것이 좋습니다. 그러나 내 실습에서 알 수 있듯이 코드 작성 및 유지 관리의 편의성이 훨씬 더 중요합니다.

그건 그렇고, 꽤 최근에 나는 코드 최적화를 만지작거리고 있었습니다. 제 Expert Advisors는 테스터에서 어떻게 든 너무 느리게 작동했습니다. 가장 느린 기능은 데이터 새로 고침이었습니다. 그래서, 나는 이 새로 고침에 대한 매력을 줄이기 위해 모든 면에서 노력했습니다. 그러나 최근에는 테스터에서 코드를 프로파일링할 수 있게 되었습니다. 그리고 놀랍게도 EA는 나를 위해 터미널 상태를 요청하는 (거의) 불필요한 기능에 대부분의 시간을 소비한다는 것을 알았습니다. 다른 사람). 그리고 무엇보다도 - 그것은 여유 메모리를 요청하는 기능에 소비되었습니다. 터미널 상태가 시작 시 한 번만 요청되고 새로 고침 중에(명시적으로 지정된 경우에만) 코드를 약간 변경하여 테스트를 3배 이상 가속화했습니다!

따라서 "불필요한 오버헤드"는 우리가 찾고 있는 곳에서 전혀 손실되지 않을 수 있습니다.

 
George Merts :

따라서 "불필요한 오버헤드"는 우리가 찾고 있는 곳에서 전혀 손실되지 않을 수 있습니다.

그와 논쟁하지 마십시오. 그것의 유일한 목적은 진정하는 것입니다. 절대로 그와 같은 것을 증명하지 마십시오. 그러한 캐릭터를 다루는 가장 좋은 전략은 완전히 무시하는 것입니다.
 
George Merts :

왜 "바보"? 제 생각에 오버헤드는 매우 작으며 CObject가 목록과 정렬된 배열을 구성하기 위해 제공하는 편리함을 분명히 가치가 있습니다.

이러한 "편의성"이 한 곳에서 구현됩니다. 개체에서 무언가를 변경하는 목록은 어떤 종류입니까? 사실 상수 객체 는 목록에 넣을 수 없습니다. 또는 그러한 목록에 있는 객체를 특정 함수에 보내고 해당 함수도 해당 목록에 넣은 다음 변경된 이전 및 다음으로 객체를 다시 가져오고 우리는 가버리는 상황을 상상해 보십시오.

문명 세계에서 목록은 필요한 포인터를 저장하는 보조 노드 개체를 통해 구현됩니다. 그리고 사용자의 물건을 만지는 것은 넌센스입니다. 따라서 요점은 오버헤드뿐만 아니라 이 모든 것의 근본적인 부정확성에 있습니다. 개발자들은 급하게 무언가를 눈멀게 했고, 당신은 그렇게 되어서 기쁩니다.

 
Alexey Navoykov :

이러한 "편의성"이 한 곳에서 구현됩니다. 개체에서 무언가를 변경하는 목록은 어떤 종류입니까? 사실 상수 객체 는 목록에 넣을 수 없습니다. 또는 그러한 목록에 있는 객체를 특정 함수에 보내고 해당 함수도 해당 목록에 넣은 다음 변경된 이전 및 다음으로 객체를 다시 가져오고 우리는 가버리는 상황을 상상해 보십시오.

문명 세계에서 목록은 필요한 포인터를 저장하는 보조 노드 개체를 통해 구현됩니다. 그리고 사용자의 물건을 만지는 것은 넌센스입니다. 따라서 요점은 오버헤드뿐만 아니라 이 모든 것의 근본적인 부정확성에 있습니다. 개발자들은 급하게 무언가를 눈멀게 했고, 당신은 그렇게 되어서 기쁩니다.

네, 상수 개체를 목록에 넣을 수 없습니다.

그러나 동시에 CObject의 기능을 지속적으로 사용하고 비평가 중 누구도 표준 라이브러리의 개체, 배열 및 목록과 유사한 것을 제공하지 않았습니다.

"How to do it"은 모든 사람이 고함치는 방식입니다. 그러나 무언가를 제공하기 위해 - 갑자기 아무것도 없습니다.

실제로 다양한 소프트웨어 솔루션을 제공하는 참가자(CObject'y의 대체품을 제공하지 않음)조차도 "한 곳을 통한 구현"에 주의를 기울이지 않고 더 자주 사용하지 않고 기능을 덜 사용합니다. 따라서 구현 자체에 매우 적합합니다.

그것이 나빴다면 그들은 오래 전에 교체를 제안했을 것입니다.