c++ - 编程原理与实践第 2 版第 8 章练习 1

标签 c++ clang++

问题:

在 Bjarne Stroustrup 的编程原理与实践第 8 章中,我无法通过 clang++ 获取作者提供的代码。

代码:

 ~/scratch/cpp/chp8 (09/10/2017-13:51:43[EDT]) cat my.cpp
#include <iostream>
#include "my.h"
void print_foo() { std::cout << foo << std::endl; }
void print(int i) { std::cout << i << std::endl; }

 ~/scratch/cpp/chp8 (09/10/2017-13:52:29[EDT]) cat my.h
#ifndef MY_H
#define MY_H
extern int foo;
void print_foo();
void print(int);
#endif

 ~/scratch/cpp/chp8 (09/10/2017-13:52:33[EDT]) cat use.cpp
#include "my.h"

int main() {
  foo = 7;
  print_foo();
  print(99);
  return 0;
}

尝试:

我尝试了几种不同的编译方法:

一个 - 编译包含主要功能的驱动程序应用。

 ~/scratch/cpp/chp8 (09/10/2017-13:52:39[EDT]) clang++ -std=c++14 -stdlib=libc++  use.cpp -o use.cpp.o
Undefined symbols for architecture x86_64:
  "print(int)", referenced from:
      _main in use-2864c4.o
  "print_foo()", referenced from:
      _main in use-2864c4.o
  "_foo", referenced from:
      _main in use-2864c4.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

两个 - 具体只编译 my.cpp 文件而不编译链接。虽然我编译成功了,但我不确定现在如何将 use.cpp 与这个目标文件链接起来。

 ~/scratch/cpp/chp8 (09/10/2017-14:09:40[EDT]) clang++ -std=c++14 -stdlib=libc++ -c my.cpp -o my.cpp.o

三个 - 使用所有 .cpp 文件。

 ~/scratch/cpp/chp8 (09/10/2017-14:15:32[EDT]) clang++ -std=c++14 -stdlib=libc++ my.cpp use.cpp
Undefined symbols for architecture x86_64:
  "_foo", referenced from:
      print_foo() in my-2243d1.o
      _main in use-796f91.o
     (maybe you meant: __Z9print_foov)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

问题:

除了我做错了什么这个明显的问题之外,我更感兴趣的是我在这里遗漏或遗漏了什么?

注意:

我不是在寻找关于我应该做什么或不应该做什么的个人意见或偏好。这本书是我进行的纯粹的教育冒险,我希望保持原样。

杂项:

 ~/scratch/cpp/chp8 (09/10/2017-14:15:25[EDT]) uname -a
Darwin abes-MacBook-Pro.local 16.7.0 Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64 x86_64
 ~/scratch/cpp/chp8 (09/10/2017-14:15:28[EDT]) clang++ -v
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

最佳答案

您得到的错误与编译和链接之间的区别无关。相反,您的代码中存在错误。错误的原因是因为您声明全局变量foo,但您从未定义它。您需要添加行

int foo = 0;

到您的一个 .cpp 文件。这可能在 my.cpp 中最有意义。

请注意,像这样使用全局变量被认为是编码恐怖。您不应该在实际代码中执行此操作。

关于编译和链接:

从 C++ 创建可执行文件需要几个步骤。在这里,我们将讨论编译与链接以及如何手动执行这些步骤中的每一个。还有其他步骤,但我不会在这里详细介绍。

首先,您可以一次编译并链接所有源文件:

$ clang++ -std=c++14 -stdlib=libc++ my.cpp use.cpp

我很困惑为什么这在您的“第三次尝试”中不起作用。我稍后会对此进行更深入的研究。

要手动编译和链接您的源代码,您可以执行以下操作:

$ clang++ -std=c++14 -stdlib=libc++ -c my.cpp -o my.o
$ clang++ -std=c++14 -stdlib=libc++ -c use.cpp -o use.o
$ clang++ -std=c++14 -stdlib=libc++ my.o use.o -o use

请注意,我将 my.cpp 编译为 my.o 而不是 my.cpp.o。这是对此的通用约定。

此外,一旦您熟悉了这些概念,我强烈建议您使用构建工具,例如 make 或自动为您管理这些步骤的 XCode 项目。

关于c++ - 编程原理与实践第 2 版第 8 章练习 1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46144024/

相关文章:

c++ - Doxygen 不会解析对命名空间中 typedef 的引用

c++ - 这种类型的模板参数是什么意思 - `ClassA<T> T::*ELEM` ?

c++ - QFileSystemWatcher 不发送 fileChanged() 信号

c++ - Clang 3.5.0 std::wregex 编译错误

c++ - g++ 和 clang++ SFINAE 和 SFINAE 失败的不同行为

c++ - 在 C++ 中获取命名空间名称的任何可移植技巧?

c++ - C++ 中的全局变量

c++ - clang++ - 将模板类名视为类范围内的模板

c++ - 在 Windows 中使用 CMake 和 clang++ 设置链接器子系统

macos - 如何在 OS X 中为 clang 启用浮点异常?