ambiguous call to overloaded function with the same parameters

 

Как понять что хочет компилятор при такой ошибке?

Есть у меня 2 класса. Один для работы с позициями, а другой для работы с отложенными ордерами. Методы у них называются одинаково в основном.

Класс, предназначенный для работы с отложенными ордерами уже не первый месяц проверен на реале.

А сегодня понадобилось кое-какие манипуляции произвести с рыночными позициями.Им я ещё не пользовался. Заинклюдил в бота на прямую т.к. нужен метод один в нём. Вижу ошибку:

'getSymbol' - ambiguous call to overloaded function with the same parameters	PositionsInfo.mqh	55	7
could be one of 2 function(s)	PositionsInfo.mqh	55	7
   string getSymbol()	PositionsInfo.mqh	14	11
   string getSymbol()	OrdersInfo.mqh	14	11
implicit conversion from 'number' to 'string'	PositionsInfo.mqh	55	7
'getMagic' - ambiguous call to overloaded function with the same parameters	PositionsInfo.mqh	57	7
could be one of 2 function(s)	PositionsInfo.mqh	57	7
   ulong getMagic()	PositionsInfo.mqh	13	11
   ulong getMagic()	OrdersInfo.mqh	13	11
'getType' - ambiguous call to overloaded function with the same parameters	PositionsInfo.mqh	71	9
could be one of 2 function(s)	PositionsInfo.mqh	71	9
   ENUM_POSITION_TYPE getType()	PositionsInfo.mqh	12	22
   ENUM_ORDER_TYPE getType()	OrdersInfo.mqh	12	19

Я так понимаю, что компилятор ругается на то, что ему неясно какую из перегрузок функции getSymbol() нужно вызывать.

Вот функция из этого класса PositionsInfo на который ругается компилятор:

//==================================================================================================================================================================================
// Возвращает true, если позиция на индексе posIndex в цикле перебора позиций 'своя', иначе false. =================================================================================
bool PositionsInfo :: choicePositionsPrimary(const string symbolName,    // Название торгового инструмента
                                             const ulong magic,          // Magic number позиции
                                             uint posIndex) {            // Индекс ордера в цикле по PositionsTotal()
//---
  if (PositionGetTicket(posIndex) == 0)
    return false;
  if (getSymbol() != symbolName)
    return false;
  if (getMagic() != magic)
    return false;
//---
  return true;
}

Вот импорты функций этих в хэдере:

#import   "GetPositionInfo.ex5"
  ENUM_POSITION_TYPE getType(void);    // Возвращает тип позиции
  ulong   getMagic(void);              // Возвращает magic number позиции
  string  getSymbol(void);             // Возвращает символ торгового инструмента по которому открыта позиция
  ulong   getTicket(void);             // Возвращает тикет позиции
#import

В библиотеке они реализованы просто. Обычные wpapper'ы для вызова этих функции интуитивно с удобством, что бы не прописывать такие вот километровые вызовы (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)  и не отвлекаться на это всё, а уделять больше внимания программированию торговой логики. Вот эти функции:

ulong getTicket(void) export {
  return (ulong)PositionGetInteger(POSITION_TICKET);
}
ulong getMagic(void) export {
  return (ulong)PositionGetInteger(POSITION_MAGIC);
}
string getSymbol(void) export {
  return PositionGetString(POSITION_SYMBOL);
}
ENUM_POSITION_TYPE getType(void) export {
  return (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}

Перегрузка видна какая. Что компилятору нужно я не понял. Это баг или что-то есть, что я мог всё-таки не учесть?

 

В общем, я понял касяк. Тока не совсем понял как подобное избегать. Компилятор видимо в ЬТ это сам не разруливает. Объясняю ситуацию.

В самом боте вот такие 2 строки идут вподряд:

#include  <HOZ_Code\Classes\TransactionHandling\PositionsInfo.mqh>
#include  <HOZ_Code\Classes\TransactionHandling\OrdersHandling.mqh>

В классе OrdersHandling есть такая строка:

#include  <HOZ_Code\Classes\TransactionHandling\OrdersInfo.mqh>

Проблема в том, что Оба класса OrdersInfo и PositionsInfo импортируют библиотеки с одинаково названными функциями. С одной лишь разницей.

В классе OrdersInfo импортируются вот что:

#import   "GetOrderInfo.ex5"
  ENUM_ORDER_TYPE getType(void);    // Возвращает тип ордера
  ulong   getMagic(void);     // Возвращает magic number ордера
  string  getSymbol(void);    // Возвращает символ торгового инструмента по которому выставлен ордер
  ulong   getTicket(void);    // Возвращает тикет ордера
#import

А в классе PositionsInfo вот что:

#import   "GetPositionInfo.ex5"
  ENUM_POSITION_TYPE getType(void);    // Возвращает тип позиции
  ulong   getMagic(void);              // Возвращает magic number позиции
  string  getSymbol(void);             // Возвращает символ торгового инструмента по которому открыта позиция
  ulong   getTicket(void);             // Возвращает тикет позиции
#import

Соответственно, и получает, как я понял в этом моменте касяк. Т.к. тип у getType() в обоих импортах разный. По ходу, это и служит причиной этих всех посылов компилятора. Отсюда возник вопрос:

Как можно ограничить импорт функций, да и классов, в том числе, в файл(класс), где они импортятся и, что бы они по цепочке не виделись во всех файла, в которых вызываемый файл, импортирующий что-либо, находится?

 
Viktar Dzemikhau:

В общем, я понял касяк. Тока не совсем понял как подобное избегать. Компилятор видимо в ЬТ это сам не разруливает. Объясняю ситуацию.

В самом боте вот такие 2 строки идут вподряд:

В классе OrdersHandling есть такая строка:

Проблема в том, что Оба класса OrdersInfo и PositionsInfo импортируют библиотеки с одинаково названными функциями. С одной лишь разницей.

В классе OrdersInfo импортируются вот что:

А в классе PositionsInfo вот что:

Соответственно, и получает, как я понял в этом моменте касяк. Т.к. тип у getType() в обоих импортах разный. По ходу, это и служит причиной этих всех посылов компилятора. Отсюда возник вопрос:

Как можно ограничить импорт функций, да и классов, в том числе, в файл(класс), где они импортятся и, что бы они по цепочке не виделись во всех файла, в которых вызываемый файл, импортирующий что-либо, находится?

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

Да и зачем вам такой импорт? Лучше положить функции в .h - файл и его инклюдить

 

Я вчера этот вопрос уже решил. Да, компилятор то не в курсе какую из тех функций нужно вызывать, т.к. типы их разные, а сигнатура одинакова.


Alexey Volchanskiy:

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

Да и зачем вам такой импорт? Лучше положить функции в .h - файл и его инклюдить

Изначально, я было дело, так и сделал. Но потом решил переделать. Ведь, по сути, библиотеки на увеличивают размер кода программы, потому что они динамически вызываются при необходимости. Если, есть пачка функций, который должны лишь возвращать какие-то значения и не более того т.е. для их выполнения не нужно хранить состояние, зачем для этого класс?

К тому же, если передавать классы, нужно контролировать жизнь указателей(дескрипторов) т.к. в мкл в основном все стандартные функции принимает дескрипторы (есс-но нет резона тогда заморчачиваться и проще ими оперировать т.к. разыменования нет. Оно как-бы есть, но не удобно. Поэтому это можно опустить). Так вот, какой резон увеличивать размер программы и всё запихивать в классы тогда? Тем более, библиотеки такие простые можно и в dll запихнуть, а класс, хотя и можно, но там не всё так просто..

Обычные инклюдники я вообще не использую, т.к. привык думать объектно. Хотя гоню.. один раз использовал пару недель назад)) Когда импортил функции из API SQLite3. Там по другому не придумалось, потому что их нужно было куда-то принять.

 
GetOrderInfo::getType() как-то так. точнее надо смотреть справку про разрешение контекста в импортах
 
TheXpert:
GetOrderInfo::getType() как-то так. точнее надо смотреть справку про разрешение контекста в импортах

Я так и вызываю статические методы классов. Просто не хотелось путать одно с другим. Я думал некоторое время, когда проектировал иерархию системы, которая у меня будем на выходе. Имею ввиду, всей иерархии клссов, бибилотек, структур и инклюдников (оказалось, что 1 всё-таки понадобился). Так вот все методы wrapper'ы было решено запихать в библиотеки. Объясню почему. Например, GetPositionInfo.mq5 у меня это библиотека с вызовами всех свойств позиций и только их. А PositionsInfo.mqh это класс, который получает различную информацию о позициях (находит требуемую позицию, подсчитывает суммарный лот нужных позиций, подсчитываемт количество позиций, в том числе и канкретного типа и тд). Т.е. библиотека лишь получает данные из неособочитабельных названий стандартных функций мкл5, а класс уже находит данные позиций.

Для ордеров имеется такая же ситуация. А для реализации торговых функций - тоже для позиций и для ордеров свои. Я вот и думаю, оставить всё как есть или перевести на статические методы классов. Ведь если прикинуть, то вызывать типа такого как у меня есть:

      if (OrdersInfo :: searchOrdersSpecifiedTypeCount(i_symbol, ORDER_TYPE_SELL_STOP, g_magic) > 0) {
        if (!prOrdersHandling.deleteLastOrderSpecifiedType(ORDER_TYPE_SELL_STOP))
          return;
      }

не совсем удобно. Да, для некоторых функций оно нормально, но для получения свойств позиций или ордеров, которые иной раз встречаются на каждой строке по многу раз это не совсем вариант. Гораздо компактнее вызывать библиотечные функции. Тем более, ещё что касяково так это то, что у меня метаэдитор не поддерживает интелленсенс т.е. не помогает писать. Статичные функции когда хочешь, что бы метаэдитор предложил дописать этого не происходит. Если предлагаешь ему комбинацией ctrl + space - не помогает. То есть писать так не очень удобно.

Причина обращения: