если функция возращает указатель на объект, а результат присваивается указателю друго типа данных

 

 билд 231 

объясните пожалуйста:

функция:


CObject *CArrayObj::At(int index)
{
//--- checking
if(index<0 || index>=m_data_total) return(NULL);
//---
return(m_data[index]);
}
 ее вызов:




 



если ее возвращаемое значение ( указатель на тип данных CObject )
присвоить указателю на тип CArray - то он становиться равен NULL
если на тип CObject - то присваевается какое то значение

так и должно производится приведение типов ( тип указателя CArray, тип возвращаемого зачения указатель на CObject) ?
если да,  то почему компилятор не дает предупреждение, что при приведении будут потеряны данные?
и почему простое присвоение на следующем шаге:

 

 



обвел, происходит нормально?
если это несоотвествие типов данных (нельзя присваивать) - то должна быть ошиба компиляции.

 

 

не нашел в справке объясните пожалуйста, что означает const 

 

int Total() const { return(m_data_total); } 

 

в определении функции

 
gdtt :

не нашел в справке объясните пожалуйста, что означает const 

 

int Total() const { return(m_data_total); } 

 

в определении функции? 


Это значит, что метод может быть вызван для константного объекта.


/******************************************************************************/
class X {
  int x;

public:
  void f(void) { x++; }
  int g(void) const { return x; }
};

/******************************************************************************/
int OnInit() {
  const X x;
//  x.f();
  return x.g();
}

Если раскомментарить "x.f();", то получим сообщение об ошибке: "'f' - call non-const method for const object".

Если метод f попытаться просто объявить const: "void f(void) const { x++; }", то получим следующее сообщение об ошибке: "'x' - cannot convert from 'const this' to 'this'" (на самом деле там должно было быть написано "from const X * to X *").


Суть происходящего можно уяснить, если понимать, что на самом деле метод - это обычная функция, которая имеет один дополнительный параметр, а именно - указатель на экземпляр объекта, от которого она вызывается.


void f(void) { x++; } есть void f(X *this) { this.x++; }
int g(void) const { } есть int g(const X *this) { return this.x; }

Если нужно, чтобы метод работал и для константного объекта, то и объявить его надо с модификатором const, но тогда уже и компилятор будет следить за тем, чтобы внутри метода объект не модифицировался.

На самом деле нужно как раз всегда, когда возможно, делать метод константным, потому что он годится и для использования с неконстантными объектами. А вот обратное - неверно.

Документация по MQL5: Стандартные константы, перечисления и структуры / Коды ошибок и предупреждений / Ошибки компиляции
Документация по MQL5: Стандартные константы, перечисления и структуры / Коды ошибок и предупреждений / Ошибки компиляции
  • www.mql5.com
Стандартные константы, перечисления и структуры / Коды ошибок и предупреждений / Ошибки компиляции - Документация по MQL5
 
simpleton :


Это значит, что метод может быть вызван для константного объекта.


спасибо, возьму на заметку.

 

посмотрите еще, пожалуйста:

 

переменные retflag == true resofret == true

 


 на следующем шаге результат операции true && true == false

 

 

 

при компиляции:

 

void func(){

};
void OnStart(){
  bool res;
  res = func();
}

нет ни предпреждения, ни ошибки компиляции.

 
gdtt :

спасибо, возьму на заметку.

 

посмотрите еще, пожалуйста:



Я не сотрудник Metaquotes, эти bug'и они сами посмотрят. Могу только сказать, что


void OnStart(){
  bool res;
  res = func();
}


разумнее сократить до


void OnStart(){
  bool res = func();
}


Bug подтверждаю для обоих вариантов. А код


  for (int i = 0; i < Total(); i++) {
    CColumn *ptr = At(i);
    bool resofret; resofret = ptr.Add();
    retflag = retflag && resofret;
  }

разумнее заменить на


  for (int i = 0; i < Total(); i++) {
    if (!At(i).Add())
      retflag = false;
  }


если метод At() возвращает "CColumn *", либо на один из вариантов


  for (int i = 0; i < Total(); i++) {
    CColumn *ptr = At(i);
    if (!ptr.Add())
      retflag = false;
  }


или


  for (int i = 0; i < Total(); i++) {
    if (!((CColumn *)At(i)).Add())
      retflag = false;
  }


если метод At() возвращает указатель на производный от "CColumn" класс.

 
simpleton :




разумнее сократить до




это не от хорошей жизни, несколько раз натыкался, на то что если использовать объявление вместе с инициализацией:

 

for (int i = 0; i < Total(); i++) {
    CColumn *ptr = At(i);
}

 то ptr запросто может быть равен NULL,  а также конструкия

 

return(ptr.Add(i));

возвращает в присваиваемую  переменную совсем не то, что возвращает метод Add, поэтому пока приходится писать длинно.

 
gdtt :

это не от хорошей жизни, несколько раз натыкался, на то что если использовать объявление вместе с инициализацией:

 

 то ptr запросто может быть равен NULL,  а также конструкия

 

возвращает в присваиваемую  переменную совсем не то, что возвращает метод Add, поэтому пока приходится писать длинно.

 

 



Да...


Мне даже в голову не пришло ЭТО тестировать...


Раз MT5 пока ещё в таком состоянии, писать под него пока ничего ещё нельзя.

Пробовать что-то совсем маленькое с целью знакомства и походу альфа-тестировать - можно, а писать...


Нет, не успеют они к осени 2010, только к осени 2011.

Там же ещё, кроме самого языка, библиотеку отлаживать и тестер, который ещё даже не готов...

 
gdtt :


 на следующем шаге результат операции true && true == false

Интересный эффект, спасибо за сообщение, исправим.

 
class simple{
  public: int contens;
};
int func(  simple* param ){
  simple* inst;
  inst = new simple;
  inst.contens = param.contens+1; //это строка 7
  //Print(inst.contens);
  return( 1 );
}
void OnStart(){
  simple inst;
  inst.contens = 1;
  Print(func(GetPointer(inst)));
}

работает, если убрать коммент в строке 8:

 

class simple{
  public: int contens;
};
int func(  simple* param ){
  simple* inst;
  inst = new simple;
  inst.contens = param.contens+1; //это строка 7
  Print(inst.contens);
  return( 1 );
}
void OnStart(){
  simple inst;
  inst.contens = 1;
  Print(func(GetPointer(inst)));
}
ошибка исполнения: 

 

2009.12.15 22:26:09 tstcall (EURUSD,H4) Invalid pointer access in 'tstcall.mq5' (7,18)
 

 

еще обратите внимание, что нет 

 

delete inst ;

в функции func

память не освобождается, раньше было сообщение об утечке памяти, сейчас его нет, значит ли это, что среда сама за ней следит и не нужно заботится об ее освобождении? 

 

 


объясните, пожалуйста, почему результат выполнения скрипта:

 

 

void OnStart(){
  datetime Arr[];
  Print( CopyTime(Symbol() , PERIOD_D1, 0, 1, Arr) );
}

разный, непредсказуемо разный:

 

 

ра 

 

 результат то 0, то 1. 

- шаг 1, результат 0, что он означает? если ошибка, доступа, что то там не подкачалось, то должен быть -1

- шаг 2 - возвратила 1, ну наверно подкачались недостающие котировки и теперь как и должно быть скопировался в массив один элемент

- шаг 3 - через некоторое время опять возвратила 0

- шаг 4 - опять 1

и так далее 

 
gdtt :

объясните пожалуйста:

1) если ее возвращаемое значение ( указатель на тип данных CObject ) 
    присвоить указателю на тип CArray - то он становиться равен NULL
    если на тип CObject - то присваевается какое то значение
2) почему компилятор не дает предупреждение, что при приведении будут потеряны данные?
3) почему простое присвоение на следующем шагепроисходит нормально?
4) переменные retflag == true resofret == true, на следующем шаге результат операции true && true == false

5) участие void функций в операциях. нет ни предпреждения, ни ошибки компиляции

Спасибо за сообщения.

 

1) осмелюсть предположить, что возвращаемый объект не может быть приведён к CArray  (он им не является)
2) Компилятор проверил и согласно наследованию приведение допустимо
3) Это наша ошибка. Исправлено
4) Это наша ошибка. Исправлено
5) Это наша ошибка. Исправлено