2013-11-27 3 views
0

У меня есть некоторые проблемы с C++. Я создаю приложение, используя библиотеку GAlib (это C++ библиотека компонентов генетического алгоритма - http://lancet.mit.edu/ga/).Как передать аргумент функции - со ссылкой

В одном из примеров (полный код примера: http://lancet.mit.edu/galib-2.4/examples/ex6.C) автор создать функцию, которая инициализирует дерево:

void TreeInitializer(GAGenome & c) 
{ 
    GATreeGenome<int> &child=(GATreeGenome<int> &)c; 

// destroy any pre-existing tree 
    child.root(); 
    child.destroy(); 

// Create a new tree with depth of 'depth' and each eldest node containing 
// 'n' children (the other siblings have none). 
    int depth=2, n=2, count=0; 
    child.insert(count++,GATreeBASE::ROOT); 

    for(int i=0; i<depth; i++){ 
    child.eldest(); 
    child.insert(count++); 
    for(int j=0; j<n; j++) 
     child.insert(count++,GATreeBASE::AFTER); 
    } 
} 

Он вызвать функцию таким образом:

genome.initializer(TreeInitializer); 

и Он не проходят Аргумент. Когда я пытаюсь передать аргумент этой функции, изменяя объявление, например:

void TreeInitializer(GAGenome &, int deph); 

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

Как передать больше аргументов этой функции?

+2

Он передает указатель на функцию. 'genome.initializer' берет указатель и вызывает функцию столько раз, сколько нужно. Если вы хотите, чтобы функция принимала больше аргументов, вам нужно сначала изменить тип (подпись) ожидаемой функции (что-то вроде 'void (* f) (GAGenome &, int)'), а затем каждый раз, когда вызовы 'initializer' 'f', передайте дополнительный аргумент. – riv

ответ

2

Линия genome.initializer(TreeInitializer); не вызывает TreeInitializer - вместо этого, он передает указатель на эту функцию в genome.initializer, так что он может назвать его какие аргументы ему нужны/несколько раз. Если вы хотите, чтобы TreeInitializer принимал больше аргументов, вам необходимо изменить initializer, чтобы принять другой тип функции. Это, вероятно, определяется как

void initializer(void (*f)(GAGenome&)) 
{ 
    // ... 
    f(genome); 
    // ... 
} 

Вам нужно изменить тип аргумента в void (*f)(GAGenome&, int) и изменить строки, которые требуют f.

С другой стороны, если вы не можете изменить функцию инициализатора, но хотите указать глубину, то лучшее, что вы можете сделать, это сделать глобальную переменную, установленную на любую необходимую глубину, и иметь TreeInitializer используйте эту переменную. Это не чистое решение, если вы считаете, что глобальные переменные являются злыми, но это ваш единственный выбор, если initializer не позволяет вам предоставлять какой-либо «контекст».

+0

У меня есть больше переменных для передачи, поэтому я не хотел использовать глобальные переменные, но знаю, я думаю, что это самый быстрый способ. Я нашел в библиотеке код: typedef void (*Initializer)(GAGenome &); и далее void initialize(){_evaluated=gaFalse; _neval=0; (*init)(*this);} Initializer initializer() const {return init;} Initializer initializer(Initializer op){return (init=op);} Так что это немного отличается от этого и вашего примера. Что я должен изменить? –

+1

Если вы действительно хотите изменить библиотечный код, чтобы позволить вам передать дополнительный аргумент (до вас, чтобы выяснить, имеет ли он смысл), тогда вам нужно добавить второй аргумент в typedef ('typedef void (Initializer) (GAGenome &, int) '), затем добавьте член int в класс, сделайте способ его установки (возможно, из функции' initializer') и получите 'initialize()' call' (* init) (* this, value) ', где' value' - это переменная-член, которую вы добавили. – riv

-1

Что вы, что делать в

GATreeGenome<int> &child=(GATreeGenome<int> &)c; 

является отливка из GAGenome в GATreeGenome. Если у вас нет оператора литья для этого случая, он не будет работать ...

+0

Литой __will__ работает, даже если оператор преобразования не предусмотрен. Ваш ответ не затрагивает фактический вопрос. -1. –

+0

Почему? GATreeGenome и GaGenome - это два разных класса. – peterh

+0

Приведение к несвязанному типу приведет к неопределенному поведению, но приведение будет выполнено __still__. Если 'GATreeGenome ' выводит GaGenome', используется 'static_cast', иначе будет использоваться' reinterpret_cast'. 'class Foo {}; класс Bar {}; const Bar & ptr = (Bar &) Foo(); // cast still happens.' –

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