与头文件一起使用时,使用个人 C++ 库编译代码会中断

Posted

技术标签:

【中文标题】与头文件一起使用时,使用个人 C++ 库编译代码会中断【英文标题】:Compiling code using personal C++ library breaks when used in conjunction with header files 【发布时间】:2019-12-24 18:37:43 【问题描述】:

我有一些跨项目使用的 C++ 实用程序函数。 我想从这些实用程序中创建一个库来为项目提供服务,而无需复制/粘贴我可能进行的任何更改。

我可以将单个 .cpp 文件转换为库:

$ g++ -c util.cpp
$ ar rcs libutil.a util.o

并制作了一个包含所有功能的 util.h 头文件。

这个库用于编译和运行一个简单的 test.cpp,它使用库函数打印一个点和一个向量的平均值:(我将标头移动到 ~/.local/include/ 并将库移动到 ~/ .local/lib/)

$ g++ -o test test.cpp -L ~/.local/lib/ -lutil
$ ./test
.
4.5

但是,当我尝试使用库编译(部分)项目时,出现“function is not declared in this scope”错误。

$ g++ -c source/linreg.cpp -L ~/.local/lib/ -lutil
...
linreg.cpp:11:18: error: ‘vecMean’ was not declared in this scope
...

试图重现这种行为我写了这个:

// header.h
#ifndef HEADER_H
#define HEADER_H

void test();

#endif

// main.cpp
#include "header.h"
#include "util.h"

int main()

    dot();
    test();
    return 0;


// test.cpp
#include <string>
#include <vector>
#include <iostream>
#include "util.h"
#include "header.h"

void test()

  dot();
  std::vector<double> x;
  for(int i = 0; i < 10; ++i)
      x.push_back(i * 1.0);
  std::cout << vecMean(x) << std::endl;

不编译。 取决于哪个#includes 在另一个之前, 抛出不同的错误。

上面的抛出“'dot'没有在这个范围内声明”, 而下面的抛出“'test'没有在这个范围内声明”

// main.cpp
#include "util.h"
#include "header.h"
...

这与我尝试编译实际项目时看到的行为相同。

如果我从 main.cpp 中删除 dot() 调用,则示例编译并运行良好,除非将 util.h 包含语句放在 header.h 之前(尽管我猜 util.h 包含没有意义)。这会导致未声明“测试”。

我觉得我错过了一些明显的东西, 尽管学习建立图书馆的整个过程很艰难。

看到头文件似乎是我在下面添加 util.h 的问题的一部分, 以及 util.cpp,很好衡量。

#ifndef HEADER_H
#define HEADER_H

#include <vector>
#include <tuple>
#include <fstream>
#include <string>

/***** utils *****/
// smallest/largest value from a vector
int indexSmallest(const std::vector<double> &vec);
int indexLargest(const std::vector<double> &vec);
// some vector operations
std::vector<double> sclMult(const std::vector<double> &vec, double scl);
std::vector<double> sclAdd(const std::vector<double> &vec, double scl);
std::vector<double> vecAdd(const std::vector<double> &vec1, const std::vector<double> &vec2);
std::vector<double> vecSub(const std::vector<double> &vec1, const std::vector<double> &vec2);
std::vector<std::vector<double> > vecCat(const std::vector<double> &vec1,
                                         const std::vector<double> &vec2,
                                         const std::vector<double> &vec3);
double vecMean(const std::vector<double> &vec);
double vecSum(const std::vector<double> &vec);
// sort two vectors of length 3 by the elements in the err vector
std::tuple<std::vector<std::vector<double> >, std::vector<double> >
  sort(const std::vector<std::vector<double> > &X, const std::vector<double> &err);
// return maximum and minimum values from vector
std::vector<double> topbot(std::vector<double> &vec);
// print a dot
void dot(std::string str = ".");
// print a vector of doubles
void printVec(std::vector<double> vec);
// print a matrix of doubles
void printMat(std::vector<std::vector<double> > mat);

#endif
#include <vector>
#include <tuple>
#include <cmath>
#include <iostream>
#include <string>

#include "util.h"

int indexSmallest(const std::vector<double> &vec)

  int index = 0;
  for(int i = 1; i < vec.size(); i++)
    
      if(vec[i] < vec[index])
        index = i;
    
  return index;


int indexLargest(const std::vector<double> &vec)

  int index = 0;
  for(int i = 1; i < vec.size(); i++)
    
      if(vec[i] > vec[index])
        index = i;
    
  return index;


std::vector<double> sclMult(const std::vector<double> &vec, double scl)

  std::vector<double> vvec(vec.size());
  for(int i = 0; i < vec.size(); i++)
    vvec[i] = vec[i] * scl;
  
  //printVec(vvec);
  return vvec;

std::vector<double> sclAdd(const std::vector<double> &vec, double scl)

  std::vector<double> vvec(vec.size());
  for(int i = 0; i < vec.size(); i++)
    vvec[i] = vec[i] + scl;
  return vvec;

std::vector<double> vecAdd(const std::vector<double> &vec1, const std::vector<double> &vec2)

  std::vector<double> vvec(vec1.size());
  //std::cout << "aaaa ";
  //printVec(vec1);
  for(int i = 0; i < vec1.size(); i++)
    vvec[i] = (vec1[i] + vec2[i]);
  
  return vvec;

std::vector<double> vecSub(const std::vector<double> &vec1, const std::vector<double> &vec2)

  std::vector<double> vvec(vec1.size());
  for(int i = 0; i < vec1.size(); i++)
    vvec[i] = (vec1[i] - vec2[i]);
  //vvec.push_back(vec1[i] - vec2[i]);
  return vvec;

std::vector<std::vector<double> > vecCat(const std::vector<double> &vec1,
                                         const std::vector<double> &vec2,
                                         const std::vector<double> &vec3)

  std::vector<std::vector<double> > vecCat(3);
  vecCat[0] = vec1;
  vecCat[1] = vec2;
  vecCat[2] = vec3;
  return vecCat;

std::tuple<std::vector<std::vector<double> >, std::vector<double> >
sort(const std::vector<std::vector<double> > &X, const std::vector<double> &err)

  //std::cout << X.size() << ' ' << err.size() << std::endl;
  std::vector<double> sortErr(3);
  //std::vector<std::vector<double> > sortX;
  int small = indexSmallest(err), large = indexLargest(err);
  if(small == large)
    return std::make_tuple(X,err);
  int middle = fabs(small + large - 3);
  //std::cout << small << ' ' << middle <<  ' ' << large << std::endl;
  sortErr[0] = err[small];
  sortErr[1] = err[middle];
  sortErr[2] = err[large];
  std::vector<std::vector<double> > sortX = vecCat(X[small],X[middle],X[large]);
    /*  sortX[0] = X[small];
  sortX[1] = X[middle];
  sortX[2] = X[large];*/
  return std::make_tuple(sortX,sortErr);


double vecMean(const std::vector<double> &vec)

  double sum = 0;
  for(int i = 0;i < vec.size();i++)
    sum += vec[i];
  
  return sum / vec.size();

double vecSum(const std::vector<double> &vec)

  double sum = 0;
  for(int i = 0;i < vec.size();i++)
    sum += vec[i];
  
  return sum;


void dot(std::string str)

  std::cout << str << std::endl;


std::vector<double> topbot(std::vector<double> &vec)

  double top = vec[0];
  double bot = vec[0];
  for(int i = 1; i < vec.size(); ++i)
    if(vec[i] > top)
      top = vec[i];
    if(vec[i] < bot)
      bot = vec[i];
  
  std::vector<double> topbot = top,bot;
  return topbot;


void printVec(std::vector<double> vec)

  for(int i = 0; i < vec.size(); ++i)
    std::cout << vec[i] << ',';
  
  std::cout << std::endl;

void printMat(std::vector<std::vector<double> > mat)

  for(int i = 0; i < mat.size(); ++i)
    printVec(mat[i]);
  


std::vector<double> head(std::vector<double> vec, int n)

  std::vector<double> head;
  for(int i = 0; i < n; ++i)
    head.push_back(vec[i]);
  return head;

std::vector<double> tail(std::vector<double> vec, int n)

  std::vector<double> tail;
  for(int i = vec.size() - n; i < vec.size(); ++i)
    tail.push_back(vec[i]);
  return tail;

std::vector<double> normalize(std::vector<double> vec)

  std::vector<double> tb = topbot(vec);
  std::vector<double> norm;
  for(int i = 0; i < vec.size(); ++i)
    norm.push_back((vec[i] - tb[1]) / (tb[0] - tb[1]));
  return norm;

std::vector<double> vecLog(std::vector<double> vec)

  std::vector<double> logged;
  for(int i = 0; i < vec.size(); ++i)
    logged.push_back(std::log(vec[i]));
  return logged;

std::vector<double> vecExp(std::vector<double> vec)

  std::vector<double> logged;
  for(int i = 0; i < vec.size(); ++i)
    logged.push_back(std::exp(vec[i]));
  return logged;

【问题讨论】:

【参考方案1】:

问题是您在两个标题中都有相同的包含保护:

#ifndef HEADER_H
#define HEADER_H

那么两个文件之一——这里是util.h——被跳过了,因为这个符号实际上已经被定义了。

我还可以根据经验建议您将库命名为更独特的名称(例如,verkutil),并使用包含保护来匹配?我的经验是太多项目有自己的UTIL_H 符号和类似命名的文件。

【讨论】:

感谢您的回答!阅读包含警卫,这很有意义,我现在有我的例子。我同意这个名字很笼统,所以我很快就会改变它。

以上是关于与头文件一起使用时,使用个人 C++ 库编译代码会中断的主要内容,如果未能解决你的问题,请参考以下文章

混合来自不同编译器的 C++ 代码

zlib1.2.11静态库使用

C++ 标准库如何链接到我的应用程序?

keilc中怎么使一个库函数不调用时不编译

过度包含库 C++

无法使用 Xcode 和终端在 Mac OS 上使用 OpenGL 库编译 c++ 文件