【问题标题】:c++ calling a function outside the class definition in a function in the classc++ 在类中的函数中调用类定义之外的函数
【发布时间】:2016-10-15 19:59:50
【问题描述】:

编辑: 我更新了代码,希望现在更具体。基本上我试图使用 dlib 库来提取特征。我需要在函数 get_features(在类定义中)中使用哈希表词汇,但我想在获取函数 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_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_features 中调用 getVocab?也就是在函数get_features之前给变量vocab赋值,并在函数内部使用。

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

【问题讨论】:

  • 为什么会被否决?
  • @Rodger 你为什么投票?有什么好的推理吗?
  • 是的,这是个好问题。我也不知道该怎么做。代码呈现出来,就会有明确的答案等等。
  • @WhozCraig 我添加了代码行,如 cmets 所示,并将尝试您的建议
  • @Hai 好的。 现在说得通了。我认为你只需要一个修改过的默认构造函数..

标签: c++ variables scope


【解决方案1】:

对冲赌注 我理解您的问题,您可以通过多种方式做到这一点。其中之一如下:

  1. 定义一个备用的默认构造函数。
  2. 在same-same的成员初始化列表中,根据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 对象设为 static var,将函数结果声明为引用类型(可能是 const),然后仅在最初加载文件时静态vocab.empty() 是真的。如:

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

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

【讨论】:

  • 感谢您提供多种解决方案。我尝试了这两种方法。不知何故,我必须在构造函数中初始化成员:feature_extractor() {vocab = getVocab();} ...但它现在可以工作了。
  • @Hai 没问题。我提供的两个示例中都显示了使用 成员初始化 的语法。我建议这样做,尤其是在后一种情况下,这不是建议;它是强制性的(引用必须总是被初始化)。祝你好运。
【解决方案2】:

我了解到您想使用函数 getVocab 来初始化您的类 feature_extractor 的成员。您可以在构造函数中执行此操作(如 WhozCraig 所建议的)。如果函数 getVocab 在逻辑上相关并且您只需要它以便它不会进入全局命名空间,您还可以将函数 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();
    }

};

【讨论】:

  • 谢谢。我最终在类定义中定义了函数,也使用了构造函数。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多