with
ключевое слово в Паскале может быть использованием к быстрому доступу поле записи. Кто-либо знает, имеет ли C++ что-либо подобное этому?
Исключая: у Меня есть указатель со многими полями, и я не хочу вводить как это:
if (pointer->field1) && (pointer->field2) && ... (pointer->fieldn)
то, что я действительно хочу, является чем-то вроде этого в C++:
with (pointer)
{
if (field1) && (field2) && .......(fieldn)
}
В C ++ вы можете поместить код в метод класса, на который ссылается указатель
. Там вы можете напрямую ссылаться на элементы, не используя указатель. Сделайте его встроенным
, и вы в значительной степени получите то, что хотите.
В C ++ нет такой возможности. И многие считают "WITH" в Паскале проблемой, потому что это может сделать код неоднозначным и трудным для чтения, например, трудно понять, является ли field1 членом указателя, локальной переменной или чем-то еще. Паскаль также позволяет использовать несколько переменных with, таких как «With Var1, Var2», что еще больше усложняет задачу.
Следующий подход основан на Boost. Если ваш компилятор поддерживает auto
C ++ 0x, то вы можете использовать это и избавиться от зависимости Boost.
Заявление об ограничении ответственности : пожалуйста, не делайте этого в любом коде, который должен поддерживаться или читаться кем-то другим (или даже вами в течение нескольких месяцев):
#define WITH(src_var) \
if(int cnt_ = 1) \
for(BOOST_AUTO(const & _, src_var); cnt_; --cnt_)
int main()
{
std::string str = "foo";
// Multiple statement block
WITH(str)
{
int i = _.length();
std::cout << i << "\n";
}
// Single statement block
WITH(str)
std::cout << _ << "\n";
// Nesting
WITH(str)
{
std::string another("bar");
WITH(another)
assert(_ == "bar");
}
}
Самое близкое, что вы можете получить, это объединение методов :
myObj->setX(x)
->setY(y)
->setZ(z)
для установки нескольких полей и с использованием
для пространств имен.
Я только что ответил на этот старый вопрос.
Есть три новых видео, которые вы можете посмотреть:
(Я мог бы связать только с youtube видео, но посты также включают дополнительные ссылки на код, презентации и пояснения)
-121--1461115- Использовать : установить nowrap
.. работает как очарование!
Сначала я слышал, что никому не нравится «с». Правила совершенно просты, ничем не отличаются от того, что происходит внутри класса в C++ или Java. И не забывайте, что это может вызвать значительную оптимизацию компилятора.
Несмотря на то, что я программирую в основном на Delphi, в котором есть ключевое слово with
(поскольку Delphi является производным от Pascal), я не использую with
. Как уже говорили другие: это немного экономит на наборе текста, но читать становится труднее.
В случае, подобном приведенному ниже коду, может возникнуть соблазн использовать with
:
cxGrid.DBTableView.ViewData.Records.FieldByName('foo').Value = 1;
cxGrid.DBTableView.ViewData.Records.FieldByName('bar').Value = 2;
cxGrid.DBTableView.ViewData.Records.FieldByName('baz').Value = 3;
Использование with
выглядит так
with cxGrid.DBTableView.ViewData.Records do
begin
FieldByName('foo').Value = 1;
FieldByName('bar').Value = 2;
FieldByName('baz').Value = 3;
end;
Я предпочитаю использовать другую технику, вводя дополнительную переменную, указывающую на то же самое, на что указывала бы with
. Вот так:
var lRecords: TDataSet;
lRecords := cxGrid.DBTableView.ViewData.Records;
lRecords.FieldByName('foo').Value = 1;
lRecords.FieldByName('bar').Value = 2;
lRecords.FieldByName('baz').Value = 3;
Таким образом не возникает двусмысленности, вы немного экономите на наборе текста, а смысл кода более ясен, чем при использовании with
Вероятно, самое близкое, что вы можете получить, это: (Пожалуйста, не понижайте меня; это просто академическое упражнение. Конечно, вы не можете использовать какие-либо локальные переменные в теле этих искусственных с
блоков!)
struct Bar {
int field;
};
void foo( Bar &b ) {
struct withbar : Bar { void operator()() {
cerr << field << endl;
}}; static_cast<withbar&>(b)();
}
Или, что более демонически,
#define WITH(T) do { struct WITH : T { void operator()() {
#define ENDWITH(X) }}; static_cast<WITH&>((X))(); } while(0)
struct Bar {
int field;
};
void foo( Bar &b ) {
if ( 1+1 == 2 )
WITH( Bar )
cerr << field << endl;
ENDWITH( b );
}
или в C ++ 0x
#define WITH(X) do { auto P = &X; \
struct WITH : typename decay< decltype(X) >::type { void operator()() {
#define ENDWITH }}; static_cast<WITH&>((*P))(); } while(0)
WITH( b )
cerr << field << endl;
ENDWITH;
Я вижу один случай, когда "with" действительно полезно.
В методах для рекурсивных структур данных часто бывает так:
void A::method()
{
for (A* node = this; node; node = node->next) {
abc(node->value1);
def(value2); // -- oops should have been node->value2
xyz(node->value3);
}
}
ошибки, вызванные подобными опечатками, очень трудно найти.
Используя 'with', вы могли бы написать
void A::method()
{
for (A* node = this; node; node = node->next) with (node) {
abc(value1);
def(value2);
xyz(value3);
}
}
Это, вероятно, не перевешивает все другие негативы, упомянутые для 'with', но просто интересная информация ...