c вызов функции вне определения класса в функции в классе

#c #variables #scope

#c #переменные #область видимости

Вопрос:

РЕДАКТИРОВАТЬ: я обновил код, надеюсь, теперь он более конкретный. В основном я пытался извлечь функции с помощью библиотеки dlib. Мне нужно использовать хэш-таблицу vocab в функции get_features (которая находится внутри определения класса), но я хочу присвоить значения vocab перед переходом к функции get_features, как указано в коде, который не работает. Класс feature_extractor определяется библиотекой dlib. Я новичок как в c , так и в dlib, и на самом деле я не знаю, как лучше сформулировать свой вопрос.


Теперь мой код имеет следующую структуру:

 #include <iostream>

#include <dlib/svm_threaded.h>

using namespace std;
using namespace dlib;

/*
 * Read a vocabulary file and return a map of vocab
 * ex. vocab["word-1"] = 0, vocab["word 0"] = 1, vocab["word 1"] = 2
 */
std::map<std::string,int> getVocab() {

    std::map<std::string, int> vocab;
    std::vector<string> words;

    ifstream infile("filename");
    string line;
    while (getline(infile, line)) {
        words.push_back(line);
    }
    int cnt = 0;
    for (auto w : words) {
        vocab[w] = cnt;
        cnt  ;
        }
    return vocab;
    }

class feature_extractor {
public:
    typedef std::vector<std::string> sequence_type;

    std::map<std::string, int> vocab = getVocab(); // if put here, it does NOT work.

    void get_features (
        feature_setteramp; set_feature,
        const sequence_typeamp; sentence,
        unsigned long position
    ) const
    {
    std::map<std::string, int> vocab = getVocab(); // if put here, it works.
    set_feature(vocab[sentence[position]]);
    }


}

int main() {
    // other stuff
    structural_sequence_segmentation_trainer<feature_extractor> trainer;
    sequence_segmenter<feature_extractor> segmenter = trainer.train(samples, segments);
    // other stuff

}
 

Есть ли способ, которым я могу использовать хэш-таблицу в функции get_features без вызова getVocab внутри get_features? То есть vocab присвоение переменной значения перед функцией get_features и использование его внутри функции.

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

Комментарии:

1. Почему это отклоняется?

2. @Rodger Почему вы проголосовали за это? Есть веские доводы?

3. Да, это хороший вопрос. Я тоже не знаю, как это сделать. Код представлен, в нем будет четкий ответ и т.д.

4. @WhozCraig Я добавил строку кода, как указано в комментариях, и попробую то, что вы предложили

5. @Хай ок. теперь это имеет смысл. Я думаю, вам просто нужен модифицированный конструктор по умолчанию..

Ответ №1:

Хеджирование ставки Я понимаю вашу проблему, есть несколько способов, которыми вы могли бы это сделать. Один из них приведен ниже:

  1. Определите альтернативный конструктор по умолчанию.
  2. В списке инициализации элемента указанного-же инициализируйте vocab из результата getVocab() .

Вот и все. Это будет выглядеть примерно так:

 class feature_extractor {
public:
    typedef std::vector<std::string> sequence_type;

    std::map<std::string, int> vocab;

    // constructor added here.
    feature_extractor() : vocab(getVocab()) // <=== member initialized
    {
    }

    // ... rest of your code ...
};
 

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

В качестве альтернативы вы можете создать объект vocab в getVocab() статическом var, объявить результат функции как ссылочный тип (вероятно const ) и загружать файл только изначально, если значение static vocab.empty() равно true . Например:

 std::map<std::string,int> constamp; getVocab()
{
    static std::map<std::string, int> vocab;

    if (vocab.empty())
    {
        std::vector<std::string> words;

        std::ifstream infile("filename");
        std::string line;
        while (getline(infile, line)) {
            words.push_back(line);
        }
        int cnt = 0;
        for (auto w : words) {
            vocab[w] = cnt;
            cnt  ;
        }
    }
    return vocab;
}
 

Делая это, все пользователи getVocab() получат одну и ту же ссылку на объект. Безопасность потоков может стать проблемой, поэтому в этом случае потребуется дополнительная работа, но, надеюсь, вы поняли идею. Вы также можете объединить это с предыдущими методами и сделать vocab переменную-член постоянной ссылкой, а не конкретным объектом. В этом случае все экстракторы будут использовать одну и ту же ссылку на один и тот же статический vocab объект в теле getVocab() :

 class feature_extractor {
public:
    typedef std::vector<std::string> sequence_type;

    std::map<std::string, int> constamp; vocab; // note: reference

    // constructor added here.
    feature_extractor() : vocab(getVocab()) // <=== member initialized
    {
    }

    // ... rest of your code ...
};
 

Как я уже сказал, существует несколько способов сделать это. Какой из них зависит от того, что лучше всего соответствует вашему шаблону использования.

Комментарии:

1. Спасибо за предоставление нескольких решений. Я попробовал оба метода. Каким-то образом я должен инициализировать член внутри конструктора : feature_extractor() {vocab = getVocab();} … Но теперь это работает.

2. @Hai Нет проблем. Синтаксис для использования инициализации члена показан в обоих приведенных мною примерах. Я бы посоветовал сделать это, особенно в последнем случае, когда это не предложение; это обязательно (ссылки всегда должны быть инициализированы). Желаю удачи.

Ответ №2:

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

 class feature_extractor {

private:

    std::map<std::string, int> getVocab() {
        // your code
    }

public:
    typedef std::vector<std::string> sequence_type;

    std::map<std::string, int> vocab ; 

    feature_extractor() 
    {
        vocab = getVocab();
    }

};
 

Комментарии:

1. Спасибо. В конечном счете я определил функцию внутри определения класса, а также использовал конструктор.

Ответ №3:

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