【C++从入门到放弃】C++/g++不同文件夹的编译

2023-11-06

本文大面积参考了简书资料 https://www.jianshu.com/p/2b047bcce8fa ,由于源书上存在好几处细节上的问题,比如:

class Afunc   应该是   class A
std::cout<<#include "A()"<<std::endl;    应该是  std::cout<<"#include A()"<<std::endl; 

等等,会产生一些误导,特重新整理了一版

测试环境

g++ -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

可能遇到的错误

可能遇到的错误,专门列出来,以备工作中遇到类似错误知道是什么原因造成的

./A.h:13:5: error: C++ requires a type specifier for all declarations
    A();
    ^
mainA.cpp:9:5: error: use of undeclared identifier 'A'; did you mean 'Afunc::A'?
    A a;
    ^
    Afunc::A
./A.h:13:5: note: 'Afunc::A' declared here
    A();
    ^
mainA.cpp:9:5: error: call to non-static member function without an object argument
    A a;
    ^


Undefined symbols for architecture x86_64:
  "A::A()", referenced from:
      _main in mainA-9d0067.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)


clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]

mingyuedeMacBook-Pro:cstudy3 mac$ g++ mainA.cpp A.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
mingyuedeMacBook-Pro:cstudy3 mac$ g++ mainA.cpp A.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
A.cpp:6:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
         ^~~~~
         "A.h"
1 error generated.
mingyuedeMacBook-Pro:cstudy3 mac$ 
mingyuedeMacBook-Pro:cstudy3 mac$ 
mingyuedeMacBook-Pro:cstudy3 mac$ g++ mainA.cpp A.cpp
A.cpp:6:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
         ^~~~~
         "A.h"


相同文件夹单文件

include "A.h"引入

在A文件夹里有A.h,A.cc,mainA.cc三个文件,代码及目录如下:

目录

 tree
.
├── A.cpp
├── A.h
└── mainA.cpp

0 directories, 3 files

A.h内容

 more A.h 

#ifndef CSTUDY3_A_H
#define CSTUDY3_A_H

#include <iostream>
class A
{
public:
    A();
};

#endif //CSTUDY3_A_H

## A.cpp内容
 more A.cpp 

#include "A.h"

A::A()
{
    std::cout<<"#include A() hahaa 888"<<std::endl;
}

mainA.cpp内容

 more mainA.cpp 

#include "A.h"     

int main()
{
    A a;
    return 0;
}

编译指令

g++ mainA.cpp 和 g++ mainA.cpp A.h 均会报错

 g++ mainA.cpp 
Undefined symbols for architecture x86_64:
  "A::A()", referenced from:
      _main in mainA-9d7e58.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
 
 g++ mainA.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
Undefined symbols for architecture x86_64:
  "A::A()", referenced from:
      _main in mainA-cfb0dc.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

大致意思就是 mainA-*.o文件中没有找到以A:A()的实现。
后面的指令也也同样提示,也就说明,g++并不会根据A.h文件,自动去找它的实现A.cpp。

而这两条命令相同,说明include " "引入的文件,会在当前目录搜索,并自动加入。

正确的编译命令为 g++ mainA.cpp A.cpp 或 g++ mainA.cpp A.cpp A.h

 g++ mainA.cpp A.cpp
 g++ mainA.cpp A.cpp A.h
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
mingyuedeMacBook-Pro:A mac$ 

其中g++ mainA.cpp A.cpp A.h执行时会有waring,但是可以正常编译通过
说明,A.h的实现文件A.cpp需要显式说明,而A.h可以不用明确写出。

include <A.h>引入

上面的目录结构不变,将mainA.cpp中的#inlcude "A.h"改为#include <A.h>

编译指令

g++ mainA.cpp A.cpp 会报错

$ g++ mainA.cpp A.cpp
mainA.cpp:1:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
        ^~~~~
        "A.h"
1 error generated.

说明include <>引入的文件,并不在当前目录搜索,只会在系统制定的目录搜索

正确的编译命令 g++ mainA.cpp A.cpp -I./

g++ -I参数

-I可以将include <>原本的搜索目录进行扩展。
上面的语句表示将./也就是当前目录加入到其搜索目录中。至于搜索顺序,后面讨论。。
如果同时将A.cc中的include “ ”也更改,那么结果时相同的。
至于应该使用哪种方式引入,实现文件,使用哪种方式。还没找到资料。
看过别人的库,是使用的include <>引入的。

不同文件夹单文件

include "A/A.h"引入

将上面的mainA.cc文件,移出A文件夹,和A文件夹放在同一级。

 tree
.
├── A
│   ├── A.cpp
│   └── A.h
└── mainA.cpp

修改mainA.cpp文件include部分(因为mainA.cpp已经与A.h不在同一个文件夹下了)


 more mainA.cpp 
#include "A/A.h"

int main()
{
    A a;
    return 0;
}

用刚才正确的编译命令g++ mainA.cpp A.cpp试一把,报错

 g++ mainA.cpp A.cpp 
clang: error: no such file or directory: 'A.cpp'

此时正确的编译命令为:g++ mainA.cpp A/A.cpp

题外话:cpp文件中必须采用既在include " "中标明相对路径,另外编译指令中也需要标明相对路径

include <A/A.h>引入

修改mainA.cpp文件include部分(改成include <A/A.h>)

 more mainA.cpp 
#include <A/A.h>

int main()
{
    A a;
    return 0;
}

用户刚才的编译命令会报错

 g++ mainA.cpp A/A.cpp 
mainA.cpp:1:10: error: 'A/A.h' file not found with <angled> include; use "quotes" instead
#include <A/A.h>
         ^~~~~~~
         "A/A.h"
1 error generated.

此时正确的编译命令为:g++ mainA.cpp A/A.cpp -I.

如果我们进一步修改A/A.cpp文件中的include部分呢

 more A/A.cpp 
#include <A.h>

A::A()
{
    std::cout<<"#include A() hahaa 444"<<std::endl;
}

用户刚才的编译命令会报错

 g++ mainA.cpp A/A.cpp -I.
A/A.cpp:1:10: error: 'A.h' file not found with <angled> include; use "quotes" instead
#include <A.h>
         ^~~~~
         "A.h"
1 error generated.

错误原因大概就是需要增加目录./A/ 作为搜索的目录之一

此时正确的编译命令为:g++ mainA.cpp A/A.cpp -I. -I./A/

不同文件夹多文件

在目录A中增加子目录C,及文件C.h C.cpp

 tree
.
├── A
│   ├── A.cpp
│   ├── A.h
│   └── C
│       ├── C.cpp
│       └── C.h
├── a.out
└── mainA.cpp

 more A/C/C.h 
#ifndef CSTUDY3_C_H
#define CSTUDY3_C_H

#include <iostream>
class C {
public:
    C();
};

#endif //CSTUDY3_C_H

 more A/C/C.cpp 
#include "C.h"

C::C() {
    std::cout << "C()" << std::endl;
}

刚才的编译命令可以编译通过
g++ mainA.cpp A/A.cpp -I. -I./A/

说明:尽管新增了文件夹及cpp文件,只要mainA.cpp中没有引用,就不用管

修改mainA.cpp文件如下:

#include <A/A.h>
#include <A/C/C.h>

int main()
{
    A a;
    C c;
    return 0;
}

再次执行上面的编译命令就会报错

  g++ mainA.cpp A/A.cpp -I. -I./A/
Undefined symbols for architecture x86_64:
  "C::C()", referenced from:
      _main in mainA-d53a4c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

正确的编译命令为:

 g++ mainA.cpp A/A.cpp A/C/C.cpp  -I. -I./A/

说明:这里没有加 -I./A/C/ 也是可以的,这是由于A/C/C.cpp中include采用的是#include “” 方式,而不是#include <>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++从入门到放弃】C++/g++不同文件夹的编译 的相关文章

  • 无法使用 strptime() 获取秒数

    我收到 YYYY MM DDThh mm ss S Z hh mm 这种格式的日期时间 我正在尝试使用复制该值strptime如下所示 struct tm time 0 char pEnd strptime datetime Y m dT
  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • 部署 MVC4 项目时出错:找不到文件或程序集

    过去 我只需使用 Visual Studio 2012 发布到 AWS 菜单项即可部署我的 MVC4 网站 到 AWS Elastic Beanstalk 现在 程序可以在本地编译并运行 但无法部署 从消息来看 它似乎正在寻找不在当前部署的
  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似

随机推荐

  • AcWing 3708. 求矩阵的鞍点

    输入样例 3 4 1 2 3 4 1 2 3 4 1 2 3 4 输出样例 1 4 4 2 4 4 3 4 4 include
  • mysql安装(Linux中redhat版本,redhat密码破解)

    破解密码 1 先重启系统 开始界面点击鼠标入进电脑 按下e键 2 在界面中间输入rd break 输入Ctrl x执行 3 输入下面命令 修改命令 mount o 是字母o不是数字0 remount rw sysroot chroot sy
  • 【华为OD机试真题 python】等和子数组最小和【2022 Q4

    前言 华为OD笔试真题 python 专栏含华为OD机试真题 华为面试题 牛客网华为专栏真题 如果您正在准备华为的面试 或者华为od的机会 有任何想了解的可以私信我进行交流 我会尽可能的给一些建议 和帮您解答 PS 文中答案仅供参考 不能照
  • 操作系统实验—处理机调度算法的模拟

    操作系统实验 处理机调度算法的模拟 一 实验目的 二 实验内容 PCB进程控制块结构 设计要求 三 实验过程记录 1 算法的思路 2 主要数据结构 3 程序代码 运行效果 一 实验目的 熟悉处理器调度算法的工作原理 掌握调度算法的实现 进程
  • WEB网站常见受攻击方式及解决办法

    一个网站建立以后 如果不注意安全方面的问题 很容易被人攻击 下面就讨论一下几种漏洞情况和防止攻击的办法 一 跨站脚本攻击 XSS 跨站脚本攻击 XSS Cross site scripting 是最常见和基本的攻击WEB网站的方法 攻击者在
  • 大端小端问题总结及相关面试题

    昨天有一同学问了我一个关于大端小端的面试题 以前掌握的蛮好的现在突然之间想不起来了 回来翻了翻书 觉得现在有必要写一篇文章来记录一下这个知识点 大端小端是存储讲的是数据在内存中的存放顺序 大端存储格式就是自数据的高字节存放在低地址中 低字节
  • 数据库设计的 10 个最佳实践

    作者 Emily Williamson 译者 孙薇 责编 屠敏 出品 CSDN ID CSDNnews 以下为译文 数据库是应用及计算机的核心元素 负责存储运行软件应用所需的一切重要数据 为了保障应用正常运行 总有一个甚至多个数据库在默默运
  • make menuconfig 添加新选项

    如何在make menuconfig 界面添加新选项步骤 1 先在Linux内核源码目录下创建个新目录 哪个位置都行 一般添加新驱动时 都会在 drivers目录下创建 这里为了实验的方便就在 源码目录下创建了 mkdir hmq test
  • Visual Studio 2019(VS 2019)配置Qt开发环境(最新!)

    1 Qt下载与安装 1 Qt下载 Qt全版本下载网址 Index of archive qt 根据操作系统下载对应的安装包即可 我选择的是5 9 9的版本 2 Qt的安装 双击打开下载好的qt opensource windows x86
  • FRP代理及其在数据库安全上的实践

    1 代理 现如今的互联网世界里 代理服务已经十分常见 它通常作为一个第三方或者说中转站角色替代用户取得信息或者服务 根据代理对象的不同 代理服务可以分为正向代理和反向代理 1 1 正向代理 我们通常所说的代理一般都指的是正向代理 正向代理的
  • LlamaIndex 提供的索引

    LlamaIndex 以前称为 GPT Index 是一个开源项目 它在 LLM 和外部数据源 如 API PDF SQL 等 之间提供一个简单的接口进行交互 它提了供结构化和非结构化数据的索引 有助于抽象出数据源之间的差异 它可以存储提示
  • 严重漏洞已存在16年,数亿台打印机受影响

    聚焦源代码安全 网罗国内外最新资讯 编译 奇安信代码卫士 安全专家在惠普 Xerox 和三星使用的常用打印机驱动中找到一个严重漏洞 该漏洞编号为 CVE 201 3438 在2005年就存在于打印机驱动代码中 影响过去16年来出售的数亿台打
  • 火狐浏览器使用HttpRequester模拟发送http请求

    个人感觉网上的在线模拟http请求工具相比火狐的HttpRequester没那么实用方便 首先安装HttpRequester 打开菜单 附加组件 搜索框输入 HttpRequester 就会搜出来 然后点击安装 成功后在工具这里就会显示有H
  • Android数据的四种存储方式

    Android数据的四种存储方式 SharePreferences SQLite Contert Provider File 网络存储 作为一个完整的应用程序 数据存储的操作是必不可少的 Android系统提供了四种存储数据方式 分别为 S
  • Cache-Control浏览器缓存

    描述 同一个标签页 打开 A 站点 访问 config 接口 正常 打开 B 站点 访问 config 接口 正常 通过浏览器后退返回 A 站点 访问 config 接口 数据异常 config 返回了 B 站点的数据 测试站点数据 htt
  • 浅谈Spring切面编程AOP的实现,以及两种写法aspect和advisor

    在开发过程种 很多地方会用到Spring的AOP 之前一致使用
  • 在centos7系统下解决java程序需要依赖外部jar包的问题

    javac cp xxxx jar bbbbb java cp也可以换成 classpath 转载 https blog csdn net weixin 34023863 article details 94448291 utm mediu
  • LVS+Keepalived群集

    Keeoalived 工具介绍 专门为LVS 和 HA 设计的一款健康检查工具 专为LVS和HA设计的一款健康检查工具 支持故障自动切换 Failover 以及节点健康状态检查 Health Checking 判断LVS负载调度器 节点服务
  • cairo[00] Windows环境学习笔记——Visual Studio配置GTK

    GTK是什么 GTK是一个跨平台的前端 在本笔记中 只会用作呈现 实际绘图依然由cairo完成 配置GTK 我们可以直接通过终端来将GTK直接加载进Visual Studio的内核 这样每次新建任务就不用再进行配置 前提是你安装了Visua
  • 【C++从入门到放弃】C++/g++不同文件夹的编译

    本文大面积参考了简书资料 https www jianshu com p 2b047bcce8fa 由于源书上存在好几处细节上的问题 比如 class Afunc 应该是 class A std cout lt lt include A l