C ++程序结构

时间:2014-09-23 18:59:50

标签: c++ class

我在思考如何用C ++构建程序时遇到了一些麻烦。我正在学习一本学习C ++的书,有一次我们构建了两个类来解决问题。本书最后将这两个类放在一起,以及它们如何在一个文件中使用并运行它,这样就可以了。但我理解更正确的结构化代码将包含头文件,每个类都会得到它自己的文件,并且当我尝试编译代码时尝试构造这样的程序会导致问题。

我有两个类,Token和Token_Stream,来自其他语言我知道Token和Token_Stream应该得到自己的文件,每个应该有一个声明文件。我的主要问题是:

Token_Stream需要知道Token。初始化Token_Stream时,它会初始化令牌。我曾经认为仅仅在Token_Stream中包含令牌的声明就足够了,这就足够了,但似乎并非如此。我对使用OOP语言进行编程有点了解,但是Token_Stream不会从Token继承任何东西,也不应该(我相信)它只需要知道足以初始化令牌并存储它。我将在下面列出每个相关文件:

Token.h

// Token.h, declaration for Token

class Token
{
public:
    char kind;
    double value;

    Token(char ch);

    Token(char ch, double val);
}; //class Token

Token.cpp

// Token.cpp

#include "Token.h"

using namespace std;

Token::Token(char ch) 
    :kind(ch), value(0){}

Token::Token(char ch, double val)
    :kind(ch), value(val) {}

Token_Stream.h

// Token_Stream.h, declarations


class Token_Stream
{
public:
    Token_Stream();
    Token get();
    void putback(Token);

private:
    bool full; // do we already hold a token?
    Token buffer; // what Token do we hold?
};//class Token_Stream

Token_Stream.cpp

// Token_Stream.cpp implementation.

#include <iostream>
#include <stdexcept>
#include "Token.h" // needs to know what a Token is
#include "Token_Stream.h"

using namespace std;

/***********************************************************************
 * Token_Stream::Token_Stream()
 * 
 * Constructor for Token_Stream(), sets full = false and buffer as 0
 * Need to do :buffer(0), so we don't create an extra buffer variable
 **********************************************************************/
Token_Stream::Token_Stream()
:buffer(0)
{
    full = false; // nothing in our stream yet.
}//constructor

/***********************************************************************
 * void Token_Stream::put_back(Token t)
 * 
 * Given a token, we fill buffer and change full to true
 * 
 * Parameter: t - Token to fill buffer
 **********************************************************************/
void Token_Stream::putback(Token t)
{
    if(!full) // if its empty
    {
        buffer = t;
        full = true;
    }//if not full
    else
        throw runtime_error("buffer already full");
}// putback


/***********************************************************************
 * Token Token_Stream::get()
 * 
 * gets another token from input, or if we have one stored, gets that.
 * 
 * Returns: Token - next token in stream, either from buffer or from
 *                  input
 **********************************************************************/
Token Token_Stream::get()
{
    if(full) //if we already have something
    {
        full = false;
        return buffer;
    }

    //if we've reached here we haven't returned:

    char ch;
    cin>>ch; //get next input and switch over cases:
    switch(ch)
    {
        // if they input a valid character:
        case ';': 
        case 'q':
        case '(': case '+': case '*': case '-': case '/': case '%': 
        case ')':
            return Token(ch);
            break;

        //if they input a valid number, or lead with a decimal i.e., .5
        case '.': case '0': case '1': case '2': case '3': case '4': 
        case '5': case '6': case '7': case '8': case '9': 
        {
            cin.putback(ch);
            double val;
            cin>>val; //read it as a number
            return Token('8',val);
            break;
        }//case of valid number
        default:
            throw runtime_error("Bad Token");
    }//switch
}//get

所以这些是文件,当我尝试编译东西时,即在Token.cpp中放入一个空的int main(){},一切正常,我编译,如果我想,我可以运行main()的

但是当我尝试在Token_Stream.cpp中放入一个空的int main(){}并尝试编译它不起作用时,我正在运行:

g++ -Wall -std=c++11 -o "Token_Stream" "Token_Stream.cpp" 

我甚至没有得到行号错误,但它声称对Token :: Token(char)等的未定义引用和其余的Token构造函数,所以我猜这意味着Token_Stream.cpp需要看到更多的Token.cpp,我该怎么做?我是否只是同时编译它们?

2 个答案:

答案 0 :(得分:2)

您需要将Token.cpp链接到您的可执行文件。

g++ -Wall -std=c++11 -o "Token_Stream" "Token.cpp" "Token_Stream.cpp"

否则gcc不会找到令牌构造函数的实现。

答案 1 :(得分:0)

除了你的链接问题,如果你在程序中寻找合适的结构,你仍然需要整理你的依赖。

Token_Stream.h应该像这样开始:

// Token_Stream.h, declarations
#include "Token.h"  // Note that this include is at the top.

class Token_Stream
...

Token_Stream.cpp应该像这样开始:

// Token_Stream.cpp implementation.
#include "Token_Stream.h"  // Note that this include is at the top.

#include <iostream>
#include <stdexcept>
...

以上要点是:

  1. 每个头文件都应包含在其实现文件的顶部。
  2. 每个头文件应该包含它实际需要的所有内容,而不是更多。
  3. 这些先决条件将允许您的客户在任何需要的地方包含您的标题。