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

Programming Principles and Practice 2nd ed chapter 8 drill 1

问题:

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

代码:

 ~/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)

Two - 专门编译 my.cpp 文件而不是 link。尽管我编译成功了,但我现在不确定如何 link 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

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

int foo = 0;

到您的 .cpp 文件之一。这可能在 my.cpp.

中最有意义

请注意,像这样使用全局变量被认为是编码恐怖。你不应该在实际代码中这样做。

关于编译和linking:

从 C++ 创建可执行文件需要几个步骤。在这里,我们将讨论编译与 linking 以及如何手动执行这些步骤中的每一个。还有其他步骤,这里就不展开了。

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

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

我很困惑为什么这在您的 "Attempt three" 中不起作用。我稍后会对此进行更深入的研究。

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

$ 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 项目。