Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > переопределение оператора


Автор: VictorOff 4.10.2011, 10:38
Уважаемые форумчане, подскажите пожалуйста, можно ли решить следующую проблему:
Имеется интерфейс класса IBase и класс реализации TBase, в нем переопределен оператор ().

class IBase
{
public:
  virtual int operator()(int Value)=0;
};
//---------------------------------------------------------------------------

class TBase : public IBase
{
public:
  virtual int operator()(int Value) {return Value*2;}
};

Чтобы воспользоваться прелестями работы с переопределенным оператором необходимо использовать крайне несимпатичный синтаксис разыменования
IBase *Base=new TBase();
int iResult=(*Base)(2);  
Нельзя ли этого избежать, скажем как-нибудь через интеллектуальный указатель? 

Автор: newbee 4.10.2011, 10:43
Напиши такой интеллектуальный указатель, у которого оператор () будет вызывать оператор () своего указателя. Еще можешь вызывать так: object->operator()(1,2,3), а еще лучше не заниматься такой ерундой и дать вменяемое имя методу.

Автор: Earnest 4.10.2011, 10:49
Можно, если напишешь соответствующую обертку. Причем виртуальный это оператор или нет - по барабану.
Но придется всегда либо использовать эту обертку вместо указателя на интерфейс, либо каждый раз оборачивать указатель при вызове (), что еще менее симпатично. Еще можно макрос нарисовать.
Да и сама идея включения виртуальных операторов в интерфейс кажется мне некошерной. Оператор () у объекта - это обобщение функции; обычно принимается, что такие объекты (функторы) очень маленькие, легкие и имеют малую стоимость... и практически не имеют прочего интерфейса.

Автор: VictorOff 4.10.2011, 12:33

Спасибо всем, кто откликнулся, согласен, приведенный пример переопределения весьма скользкий, но если рассмотрим переопределение оператора преобразования

class IBase
{
public:
  virtual operator int()=0;
};
//---------------------------------------------------------------------------

class TBase : public IBase
{
public:
  virtual operator int() {
    return 293; }
};
//---------------------------------------------------------------------------

то по моему достаточно удобно было бы использовать в виде 

IBase *Base=new TBase();
int n=Base*7;

я пробовал представить как это будет выглядеть с использованием интеллектуального указателя

template <class Type >
class TSP {
private:
  Type* pointer;
public:   TSP() : pointer(new Type()) {}
  TSP(Type* p) : pointer(p) {}
  ~TSP() { delete pointer; }
  operator Type*() { return pointer; }
  Type* operator->() { return pointer; }

  operator int() {return static_cast<int> (*pointer); }
};

TSP<TBase> sp;
int n=sp*7;

но тогда из-за включения строчки «operator int() {return static_cast<int> (*pointer); }» этот ИУ будет не универсальным, а заточенным под конкретный класс. Тогда к каждому классу надо делать персональный ИУ?

Автор: newbee 4.10.2011, 13:11
Цитата(VictorOff @  4.10.2011,  13:33 Найти цитируемый пост)
IBase *Base=new TBase();
int n=Base*7;
Неудобно. А если там будет base+42, как это понимать? Как смещение по буферу или как преобразование и сложение? А (char*)buf+42 тоже должен складывать численное представление первой буквы строки с 42?

Цитата(VictorOff @  4.10.2011,  13:33 Найти цитируемый пост)
но тогда из-за включения строчки «operator int() {return static_cast<int> (*pointer); }» этот ИУ будет не универсальным, а заточенным под конкретный класс. Тогда к каждому классу надо делать персональный ИУ?
Можно сделать универсальный базовый класс-указатель и генерировать (макросами, шаблонами или вообще внешними средствами) дочерние, под определенный тип с определенными операторами. Но техническая возможнось решения задачи еще не делает эту задачу  нужной smile

Автор: Earnest 4.10.2011, 13:19
Цитата(VictorOff @  4.10.2011,  13:33 Найти цитируемый пост)
но если рассмотрим переопределение оператора преобразования

Операторы приведения еще более некошерно использовать в интерфейсах. Да еще и делать виртуальными - вообще жуть. Операторы приведения - вообще штука опасная, и должны использоваться с большим разбором... Сделай, как тебе уже советовали, метод с вменяемым именем. Ей-богу, кучи проблем избежишь. Я уж не говорю об удобстве последующего рефакторинга...

Автор: VictorOff 4.10.2011, 13:28
Всем спасибо, убедили.

Автор: math64 4.10.2011, 18:26
Кстати, инеллектуальный указатель для этого случая разрабатывать не нужно, он уже встроен в язык, называется ссылка
Код

void test() {
IBase& RBase = *new TBase();
int n1 = RBase(2);
int n2 = (int)RBase+42;
delete &RBase;
}

Но все же вместо оператора лучше использовать обычную функцию

Автор: mes 4.10.2011, 23:58
Цитата(VictorOff @  4.10.2011,  09:38 Найти цитируемый пост)
переопределение оператора, возможно ли без разыменования указателя

 smile 
само переопределение оператора тут не причем..

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)