Проблема с переменной аргументной функцией в C ++ - PullRequest
0 голосов
/ 18 июня 2010

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

Код:

void udStaticObject::accept( udObjectVisitor *visitor, ... )
{
    va_list marker;
    udObjectVisitor *i = visitor;
    va_start( marker, visitor );
    while( 1 )
    {
        i->visit_staticObject( this );
//the if here will always go to the break immediately, allowing only 
//one argument to be used
        if( ( i = va_arg( marker, udObjectVisitor* ) ) )
            break;
    }
    va_end( marker );
}

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

Ответы [ 2 ]

5 голосов
/ 18 июня 2010

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

При передаче спискауказатели, вы можете сделать это «проще», передав нулевой указатель в качестве последнего аргумента.Таким образом, вы просто читаете аргументы, пока не достигнете нулевого указателя.

Однако , вы должны серьезно рассмотреть , а не , используя для этого переменную функцию.Вы можете выполнить то же поведение, взяв вектор указателей в качестве параметра и перебирая содержимое этого вектора.Существует несколько причин, по которым это лучше, чем использование функции с переменными числами:

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

  • При использовании вариадического решения вызывающая сторона должна правильно указать количество аргументов.Если вызывающая сторона пропускает нулевой указатель в конце (или иным образом дезинформирует вашу функцию относительно количества имеющихся аргументов), и вы пытаетесь прочитать больше аргументов, чем было передано, вы получите неопределенное поведение.Прямо сейчас вы можете сказать: «Ну, это не трудно забыть», но неизбежно, кто-то забудет или облажается, и отладка такого рода проблем - это избиение.

  • Решение, принимающеевектор и итерации по его содержимому гораздо проще реализовать, легче отлаживать и намного более идиоматичны в C ++.

Везде, где есть выбор между использованием функции с переменными числами и отсутствием использованияvariadic function, вы должны предпочесть не использовать variadic function (допустим, я никогда не писал variadic-функции ни в одном из написанного мною кода C ++, хотя я написал несколько в C).

1 голос
/ 18 июня 2010

Может быть, тест задом наперед?Попробуйте это:

    if( ( i = va_arg( marker, udObjectVisitor* ) ) != NULL )
        break;
...