【问题标题】:Calling a function from another file into another function C++将另一个文件中的函数调用到另一个函数 C++
【发布时间】:2014-05-16 00:00:56
【问题描述】:

我有一些托管函数和其他枚举的头文件。

所以在文件 Lexer.h 中,我有一个名为 getNextToken() 的函数,它返回一个令牌,在这个函数中我需要调用一个名为 reservedLookup(string tokenString) 的函数,该函数位于 token.h 中

reservedWords 是另一个名为 reservedWords.h 的头文件,其中包含保留字的枚举声明

这个函数在 token.h 中找到

reservedWords reservedLookup (string tokenString)
{
        for(rIt = reservedMap.begin(); rIt!= reservedMap.end(); rIt++)
        {
            if(tokenString == (rIt->first))
            {
                return rIt->second;
            }

        }
}

在 lexer.h 中,我尝试私下(甚至在公共场合:)使用它:

reservedWords reservedLookup(string tokenString);

它可以编译,但是在函数 Token* getNextToken() 我使用时

int tokenType = reservedLookup(strBuffer);

它给了我一个错误说明:

obj\Release\main.o:main.cpp:(.text$_ZN5Lexer12getNextTokenEv[__ZN5Lexer12getNextTokenEv]+0x371)||undefined reference to `Lexer::reservedLookup(std::string)'|

我不希望我的编译器将 reservedLookup 读取为 Lexer::reservedLookup(string str) 的一部分,而是将其读取为 Token::reservedLookup(string str)

有什么办法可以做到吗?


编辑:

令牌.h

class Token
{
       .....
       .....
public:

    void reservedDeclare ()
    {
         // iterator used for looping through reservedWords

        //Taking care of the Reserved Words first

        reservedMap["function"] =  reservedWords::tkfunction;

        //if - then - else - while - halt
        reservedMap["if"] = reservedWords::tkif;
        reservedMap["else"] = reservedWords::tkelse;
        reservedMap["while"] = reservedWords::tkwhile;
        reservedMap["halt"] = reservedWords::tkhalt;

        //and, or, not, true, else
        reservedMap["and"] = reservedWords::tkand;
        reservedMap["or"] = reservedWords::tkor;
        reservedMap["not"] = reservedWords::tknot;
        reservedMap["true"] = reservedWords::tktrue;
        reservedMap["false"] = reservedWords::tkfalse;

        //sets and read/write
        reservedMap["set"] = reservedWords::tkset;
        reservedMap["let"] = reservedWords::tklet;
        reservedMap["read"] = reservedWords::tkread;
        reservedMap["write"] = reservedWords::tkwrite;

        //variable type
        reservedMap["int"] = reservedWords::tkint;
        reservedMap["char"] = reservedWords::tkchar;
        reservedMap["bool"] = reservedWords::tkbool;
        reservedMap["real"] = reservedWords::tkreal;
        reservedMap["string"] = reservedWords::tkstring;
        reservedMap["unit"] = reservedWords::tkunit;


    }

reservedWords reservedLookup (string tokenString)
{
        for(rIt = reservedMap.begin(); rIt!= reservedMap.end(); rIt++)
        {
            if(tokenString == (rIt->first))
            {
                return rIt->second;
            }

        }
}

reservedWords.h

#ifndef RESERVEDWORDS_H_INCLUDED
#define RESERVEDWORDS_H_INCLUDED

#include <string>
#include <vector> //std::vector
#include <algorithm>    // std::find

using namespace std;

/**
        All the reserved words used by the compiler

*/


    /**
        This file contains all the keywords or reserved words or reserved Symbols used by the compiler
        In the lexer, we will check whether the string we are passing is either a Reserved word
        or it is actually and identifier
    */

    enum reservedWords
    {
        tkfunction,
        tkif,
        tkelse,
        tkwhile,
        tkhalt,

        tkand,
        tkor,
        tknot,
        tktrue,
        tkfalse,

        tkset,
        tklet,
        tkread,
        tkwrite,

        tkint,
        tkchar,
        tkbool,
        tkreal,
        tkstring,
        tkunit,

        tkreservedWord,
        tkidentifier


    };

    #endif // RESERVEDWORDS_H_INCLUDED

Lexer.h 的部分代码

class Lexer
{
   private:
   string strBuffer ="";//holds the current characters that have been read and waiting to be matched
   int tokenType = 0;
   reservedWords reservedLookup(string tokenString); // THIS DOES NOT WORK. SEES IT AS Lexer::reservedLookup
  ....
  ....
  ...
  ...

  tokenType = reservedLookup(strBuffer); // GIVES ME ERROR BECAUSE OF ABOVE

【问题讨论】:

  • 当您的代码示例在类定义或其他上下文中时,请明确说明。
  • @aschepler 检查编辑,看看它是否有帮助...... LEXER.H 和 TOKEN.H 都在一个类中。 ReservedWords 不,只是枚举
  • 在 Lexer.h 的部分代码中,您有“这不起作用”的注释...这是 Lexer 类中的类成员函数声明吗?如果它是不是,为什么它在那里?如果是,为什么没有返回值?
  • @jeffrey_t_b 抱歉,应该读作 reservedWords reservedlookup (string tokenString) ,我尝试制作另一个头函数来调用 token.h 中的那个(正如我在其他教程中看到的那样)但它没有帮助。所有其他教程都包含 .cpp
  • tokenType = reservedLookup(strBuffer); 在函数定义中吗?如果你想让它调用Token::reservedLookup,你想让它使用什么Token对象?

标签: c++ function enums


【解决方案1】:

让我们先看看你的这部分代码:

class Token
{
  ...
public:
  ...
  reservedWords reservedLookup (string tokenString)
  {       // start of function body
    for(rIt = reservedMap.begin(); rIt!= reservedMap.end(); rIt++)
    {
        if(tokenString == (rIt->first))
        {
            return rIt->second;
        }

    }
  }       // end of function body
  ...
};

在此文件中,您声明了一个全范围名称为Token::reservedLookup 的函数。 (如果你不熟悉“全域”这个术语,好吧;就我们这里的目的而言,重要的是这是命名这个函数的一种特定方式。)我们可以在这个名称的前面写上Token::,因为该函数是Token 类的成员。您还定义了函数,提供了一个函数体(用大括号括起来的代码{})。我在函数体开始和结束的行添加了 cmets。

到目前为止,一切都很好。现在,这个函数是类Token的一个普通成员,而不是一个“静态”函数,所以为了调用它,你必须首先有一个Token类型的对象,然后你可以在那个上面调用这个函数对象,例如通过在其他函数中编写这样的代码:

Token token;
token.reservedDeclare();
reservedWords word = token.reservedLookup("read");

现在是事情变得混乱的部分。你写了这段代码:

class Lexer
{
private:
  ...
  reservedWords reservedLookup(string tokenString);
  ...
};

这样做是为了声明一个与第一个函数不同的 函数。这个函数的全称是Lexer::reservedLookup。但是,您没有提供该函数的任何定义(此处没有,显然其他任何地方都没有)。因此,当您在 Lexer 类的代码中并编写这样的一行时,

tokenType = reservedLookup(strBuffer);

编译器按照 C++ 语言规范所说的方式对此进行解释,即这应该是对函数 reservedLookup 的调用,该函数属于出现此调用的同一函数的类。简而言之,就是调用Lexer::reservedLookup。由于您从未定义过该函数,因此不可能生成正确调用该函数的代码,因此会出现错误。

所以你可能根本不想定义Lexer::reservedLookup。如果您没有从 Token 类本身的某个函数中调用 Token::reservedLookup,您可以提供一个 Token 类型的 object 以便您可以像我一样调用该函数在我的例子中。或者,您可能希望将函数定义设为静态,以便可以这样调用它,而不需要 Token 类型的对象:

reservedWords word = Token::reservedLookup("read");

但是,为了使这项工作按需要进行,您还必须将reservedDeclare 设为静态函数并将reservedMap 设为Token 的静态变量,或者进行一些其他更改,以便使用的数据Token::reservedLookup 独立于 Token 类型的特定对象而存在。

您可能还想查看此问题的答案:The Definitive C++ Book Guide and List 并阅读推荐的书籍以帮助更好地理解该语言的术语,从而获得有关您的程序的更好建议。

【讨论】:

  • 谢谢伙计!非常好的解释帮助了我很多东西。会尝试一些东西
  • 所以当函数为ClassName::Function 时,它们是完全作用域的,对吗?不好意思再问
  • @DodoSerebro:从技术上讲,没有。例如,std::string::size 其中std 是命名空间,string 是类,size 是函数。如果名称包含所有周围的类和命名空间,则该名称是完全限定的。
  • 正如@MSalters 所指出的,全范围名称并不总是只有一个::。在问题的代码中。我只是假设在我们没有看到的源文件部分中没有定义额外的范围。例如,我假设您在定义class Token 之前没有写任何类似namespace parsing { 的东西,因为那样会使全范围函数名称parsing::Token::reservedLookup
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-12
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多