使用多个文件制作和编译C ++项目 [英] Making and compiling C++ projects with multiple files

查看:58
本文介绍了使用多个文件制作和编译C ++项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C/C ++的新手,我已经掌握了基础知识,并且现在开始学习更高级的概念.

I am new to C/C++, I already know the basics and I am starting to learn more advanced concepts now.

当前,我正在使用C ++开发一个项目,这是一个很大的项目,因此构造我的项目会更好.

Currently I am developing a project using C++ and it is quite a big one, so structuring my project will be better.

据我所知,一个好的结构至少要依赖于文件夹:/src /include .所有.cpp文件应放在/src 文件夹中,而.hpp文件应放在/include 中.这里引起了第一个疑问:如何包含不在同一目录或标准目录中的标头?搜索之后,我得出结论,最好的方法是将选项 -I ../include 传递给编译器.

From what I have already seen, a good structure relies on, at least, to folders: /src and /include. All .cpp files should go in /src folder and .hpp ones in /include. Here the first doubt arose: how to include a header which is not in the same directory nor in a standard one? After searching about it I concluded that the best way is to pass the option -I../include to the compiler.

我有三个源文件:main.cpp,GraphData.cpp和RandomGraphGenerator.cpp.我已经读到,最好的做法是为每个文件都有一个标头,以将声明与定义分开.现在,我也有两个头文件,但是我不知道如何编译所有这些头文件.

I had three source files: main.cpp, GraphData.cpp and RandomGraphGenerator.cpp. I have read that it is best practice to have a header for each of these files, to separate declaration from definition. Now I also have two headers, but I am not getting how to compile all of these.

我正在集中精力使GraphData.cpp正确链接到main.cpp,我评论了需要RandomGraphGenerator.cpp的所有内容.这是我的主文件:

I am focusing making GraphData.cpp to be linked correctly to main.cpp, I commented everything that needs RandomGraphGenerator.cpp. This is my main file:

// main.cpp
#include <iostream>
#include <string>
#include <Snap.h>
#include <GraphData.hpp>

int main() {
    std::string file_path;
    char path[1024];
    DataPoint **data_set;
    int motif_size, num_null_models;

    std::cin >> file_path;
    std::cin >> motif_size;
    std::cin >> num_null_models;

    data_set = new DataPoint*[num_null_models];

    strncpy(path, file_path.c_str(), sizeof(path));
    path[sizeof(path) - 1] = 0;

    //read input
    PNGraph G = TSnap::LoadEdgeList<PNGraph>(path, 0, 1);

    //enumerate and classify k-subgraphs in G
    GD::extractData(&G, motif_size, data_set[0]);

    //generate random graphs and enumerate and calssify k-subgraphs on them
    for(int i=1; i<=num_null_models; i++) {
        //GM::randomize(&G);
        GD::extractData(&G, motif_size, data_set[i]);
    }

    //detect motifs
    GD::discoverMotifs(data_set);

    return 0;
}

我的GraphData标头:

My GraphData header:

#ifndef GRAPHDATA_HPP_INCLUDED
#define GRAPHDATA_HPP_INCLUDED

#include <Snap.h>

struct DataPoint;

namespace GD {
    void extractData(PNGraph*, int, DataPoint*);
    DataPoint* discoverMotifs(DataPoint**);
}

#endif // GRAPHDATA_HPP_INCLUDED

还有我的GraphData文件:

And my GraphData file:

#include <GraphData.hpp>

struct DataPoint {
    int label;
    int frequency = 0;
};

void GD::extractData(PNGraph* G, int k, DataPoint* data_array) {
    //stuff
}

DataPoint* GD::discoverMotifs(DataPoint** data_set) {
    //dummy code
    DataPoint* dp;
    dp = new DataPoint[2];
    dp[0].label = 10;
    dp[1].label = 99;
    return dp;
}

我试图在带有GCC 4.9.2的Ubuntu 14.10下使用:

I am trying to compile, under Ubuntu 14.10 with GCC 4.9.2, using:

g++ -o main main.cpp /usr/include/Snap-2.3/snap-core/Snap.o -I../include -I/usr/include/Snap-2.3/snap-core -I/usr/include/Snap-2.3/glib-core

但是它给了我一个不确定的裁判错误:

But it gives me an error of undefined referece:

main.cpp:(.text+0x179): undefined reference to `GD::extractData(TPt<TNGraph>*, int, DataPoint*)'
main.cpp:(.text+0x1b9): undefined reference to `GD::extractData(TPt<TNGraph>*, int, DataPoint*)'
main.cpp:(.text+0x1dd): undefined reference to `GD::discoverMotifs(DataPoint**)'
collect2: error: ld returned 1 exit status

我有点迷失了,我想念什么?

I am a little bit lost with it, what am I missing?

推荐答案

g ++默认情况下在完成所有输入文件的编译后立即调用链接程序(ld).产生二进制可执行文件的方法有很多,但是最常见的两种是:

g++ by default invokes the linker (ld) as soon as it has finished compiling all the input files. There are many ways to produce the binary executable, but the two most common are:

  1. 将所有源文件包含在单个 g ++ 命令中.您需要将 GraphData.cpp main.cpp 添加到对 g ++ 的同一调用中.此方法确保链接器可以访问所有符号以创建可执行文件.
  2. 将每个文件分别编译为目标文件,并在单独的步骤中链接它们(这在大型软件项目中更常见).为此,请将每个cpp文件的 -c 开关传递到 g ++ ,然后再次调用g ++并传递 .o 文件而不是 .cpp 文件.
  1. Include all source files in a single g++ command. You would need to add GraphData.cpp and main.cpp to the same call to g++. This method ensures the linker has access to all the symbols to create the executable.
  2. Compile each file into an object file separately and link them in a separate step (this is more common for large software projects). To do this, pass the -c switch to g++ for each cpp file, then call g++ again and pass the .o files instead of the .cpp files.

无论哪种方式,在某些时候,您都必须立即将所有符号提供给链接器,以便它可以创建可执行文件.

Either way, at some point, you have to give all the symbols to the linker at once so it can create the executable.

正如Joachim所解释的那样,除了几个文件之外,任何事情都会变得非常痛苦,在这一点上,学习构建系统可能会非常有利可图.他提到了make,但我也考虑考虑 cmake ,它的语法更简单并且是跨平台的.它甚至可以自动为您生成 Makefiles .

As Joachim explained, anything beyond a couple files becomes a huge pain, at which point learning a build system can be quite profitable. He mentions make, but I would also consider looking into cmake which has simpler syntax and is cross platform. It can even generate Makefiles for you automatically.

这篇关于使用多个文件制作和编译C ++项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆