c++在类中的函数中调用类定义之外的函数

c++ calling a function outside the class definition in a function in the class

本文关键字:函数 定义 调用 c++      更新时间:2023-10-16

编辑:我更新了代码,希望现在更具体。基本上,我试图使用dlib库提取功能。我需要在函数get_features(在类定义中(中使用哈希表vocab,但我希望在获取函数get_fFeatures之前为vocab赋值,如代码中所示,这是不起作用的。类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_setter& set_feature,
        const sequence_type& 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中的哈希表,而无需在get_feature中调用getVocab?也就是说,在函数get_features之前为变量vocab分配值,并在函数内部使用它。

我试着在f2之前的类定义中调用f1,并将哈希表分配给一个变量,但似乎不起作用。如有任何帮助,我们将不胜感激。

对冲我理解你的问题,有很多方法可以做到这一点。其中之一如下:

  1. 定义一个备用默认构造函数
  2. 在所述相同的成员初始化列表中,根据getVocab()的结果初始化vocab

就是这样。它看起来像这样:

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 ...
};

前面的代码也将参与移动语义,这也应该减少不必要的复制。

或者,您可以将getVocab()中的vocab对象设置为静态var,将函数结果声明为引用类型(可能是const(,并且仅在静态vocab.empty()为true时初始加载文件。例如:

std::map<std::string,int> const& 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成员变量成为常量引用,而不是具体对象。在这种情况下,所有提取器将共享对getVocab():主体中相同静态vocab的相同引用

class feature_extractor {
public:
    typedef std::vector<std::string> sequence_type;
    std::map<std::string, int> const& vocab; // note: reference
    // constructor added here.
    feature_extractor() : vocab(getVocab()) // <=== member initialized
    {
    }
    // ... rest of your code ...
};

正如我所说,有很多方法可以做到这一点。哪一个取决于什么最适合你的使用模式。

我知道您想要使用函数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();
    }
};

我不明白你倾向于做什么,但你可以将函数之外的哈希表声明为全局变量,这是不推荐的。