2015-09-07 3 views
-2

Я пытаюсь написать классы с цепными операторами (подобно JQuery), где вместо возврата void функция возвращает объект/указатель, на который он был вызван, чтобы вы могли выполнять на нем больше функций. Например:Можете ли вы использовать макросы для создания типа «self» return?

Foo* Foo::bar(Bar value){ 
    _bar = value; 
    return this; 
} 

Очевидно наименее хак-й способ сделать это было бы использует собственный класс объекта в качестве возвращаемого типа, как указано выше, но мне было интересно, если есть способ, чтобы сократить это с помощью макросов , Например:

self Foo::bar(Bar value){ 
    _bar = value; 
} 

Макрос в основном заменит себя классом, к которому принадлежит метод, и добавляет «return this;» к концу. Это возможно? И если да, это хорошая идея, или я должен придерживаться обычного метода?

+2

Знаете ли вы, что такое макрос? Текстовые подстановки не могут вставлять код (т. Е. 'Return this;') в любом месте, где уже нет заполнитель. –

+0

придерживаться общего соглашения. это поможет с удобочитаемостью. –

+2

Это, конечно, не будет хорошей идеей и приведет к довольно нечитаемому коду. Если вы чувствуете, что печатаете слишком много, получите лучший текстовый редактор. –

ответ

4

Я думаю, вы беспокоитесь о мелочах. За время существования проекта, разница в времени, затрачиваемого написать

Foo* Foo::bar(Bar value){ 
    _bar = value; 
    return this; 
} 

против

self Foo::bar(Bar value){ 
    _bar = value; 
} 

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

BTW, я бы рекомендовал использовать Foo& как время возврата.

Foo& Foo::bar(Bar value){ 
    _bar = value; 
    return *this; 
} 

Возврат указателя имеет смысл только в том случае, если существует вероятность того, что функция может вернуть NULL, чтобы обозначить сбой.

0

Я не рекомендую, но можно было бы не использовать такой подход, как:

#define self(T,memname,arglist) T* T::memname arglist { memname##impl REMOVETYPES(arglist); return this; } void T::memname##impl arglist 

self(Foo,bar,(Bar value)) 
{ 
    this.internal_bar = value; 
} 

Обратите внимание, что это уже не выглядит ничего подобного заявления члена. Если вы собираетесь идти в этом направлении, могли бы также сделать макрос для змеевидных сеттеров:

#define DEFINE_SETTER(T,setterName,MemType,MemName) T* T::setterName(MemType value) { MemName = value; return this; } 

DEFINE_SETTER(Foo,setBar,Bar,bar) 

Эта последняя версия, по крайней мере, очевидно, генератор кода макросов на основе, не делая вид, что странно форма реального C++.

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

+0

«Но, я думаю, я задаю вопрос о том, как заставить потребителя использовать функцию, когда нет никакой логики, просто непосредственно подвергая возможность перезаписывать переменную-член». Это был просто (плохо написанный) пример. Реальный код будет иметь встроенную логику проверки. –

Смежные вопросы