带有模板的简单 C++ 代码由于未定义的引用 [重复] 而无法编译

Simple C++ code with templates won't compile due to undefined references [duplicate]

提问人:Petri Hirvonen 提问时间:10/19/2022 更新时间:10/19/2022 访问量:77

问:

我四处寻找答案,但我仍然感到困惑。据我了解,从我在网上找到的示例中,我的代码应该是有效的,但由于未定义的引用,它不会编译。我想出了如何让它编译,但我认为这不是应该这样做的方式。因此,以下是我非常希望回答的问题。

我想在 C++ 中实现一个带有模板成员的类,类似于 std::vector 可以包含任何类型的数据。下面是重现该问题的最小示例。

main.cpp:

#include <iostream>
#include <cstdlib>

#include "Foo.h"

int main(int argc, char** argv) {
  
  Foo<int> foo_int;
  Foo<float> foo_flt;

  return 0;
}

Foo.h:

#ifndef FOO_H
#define FOO_H

template<class T> class Foo {
public:
    Foo();
    Foo(const Foo& orig) = delete;
    virtual ~Foo();
private:
    T* m_f;
};

#endif /* FOO_H */

Foo.cpp

#include <iostream>
#include <typeinfo>
#include "Foo.h"

template<class T> Foo<T>::Foo() {
  std::cout << "Constructing a Foo<" << typeid(T).name() << ">!" << std::endl;
  m_f = new T;
}

template<class T> Foo<T>::~Foo() {
  std::cout << "Destructing a Foo<" << typeid(T).name() << ">!" << std::endl;
}

现在,如果我尝试在 NetBeans IDE 中构建代码,则会得到以下输出。

cd '/home/pete/Dropbox/NetBeans/Foodinger'
/usr/bin/make -f Makefile CONF=Debug
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Entering directory '/home/pete/Dropbox/NetBeans/Foodinger'
"/usr/bin/make"  -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux/foodinger
make[2]: Entering directory '/home/pete/Dropbox/NetBeans/Foodinger'
mkdir -p build/Debug/GNU-Linux
rm -f "build/Debug/GNU-Linux/Foo.o.d"
g++    -c -g -std=c++14 -MMD -MP -MF "build/Debug/GNU-Linux/Foo.o.d" -o build/Debug/GNU-Linux/Foo.o Foo.cpp
mkdir -p build/Debug/GNU-Linux
rm -f "build/Debug/GNU-Linux/main.o.d"
g++    -c -g -std=c++14 -MMD -MP -MF "build/Debug/GNU-Linux/main.o.d" -o build/Debug/GNU-Linux/main.o main.cpp
mkdir -p dist/Debug/GNU-Linux
g++     -o dist/Debug/GNU-Linux/foodinger build/Debug/GNU-Linux/Foo.o build/Debug/GNU-Linux/main.o 
build/Debug/GNU-Linux/main.o: In function `main':
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:8: undefined reference to `Foo<int>::Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:9: undefined reference to `Foo<float>::Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:9: undefined reference to `Foo<float>::~Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:8: undefined reference to `Foo<int>::~Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:8: undefined reference to `Foo<int>::~Foo()'
collect2: error: ld returned 1 exit status
nbproject/Makefile-Debug.mk:63: recipe for target 'dist/Debug/GNU-Linux/foodinger' failed
make[2]: *** [dist/Debug/GNU-Linux/foodinger] Error 1
make[2]: Leaving directory '/home/pete/Dropbox/NetBeans/Foodinger'
nbproject/Makefile-Debug.mk:60: recipe for target '.build-conf' failed
make[1]: *** [.build-conf] Error 2
make[1]: Leaving directory '/home/pete/Dropbox/NetBeans/Foodinger'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 760ms)

我的理解是,应该只提供头文件,而.cpp文件应该作为编译器的参数。这就是构建似乎根据其输出正在做的事情。但是,如果我添加到main.cpp,程序似乎编译和运行良好。但这难道不是一个人不应该这样做的方式吗?或者我在这里发现了一些特殊情况,我必须使用 .cpp 文件?NetBeans 做错了什么吗?我使用模板的实现有问题吗?至少如果我摆脱它们,代码编译得很好。#include#include "Foo.cpp"#include

谢谢。

C++ 模板 编译 包括 undefined-reference

评论

0赞 CGi03 10/19/2022
还必须将成员函数定义放在头文件中。
0赞 user17732522 10/19/2022
与非模板化实体相比,模板化实体必须(以通常的方法)在头文件中定义。将成员函数的定义从 移动到文件。包含文件是解决此问题的糟糕方法。.cpp.h.cpp
0赞 Petri Hirvonen 10/19/2022
哦,我明白。我设法错过了这条信息。谢谢。
0赞 user4581301 10/19/2022
旁注:如果你写了一个好的标题(你在这里点赞!)将标题粘贴到谷歌中,看看会出现什么。在这种情况下,第一次命中是重复命中之一。谷歌玩游戏时会根据你过去的历史记录对结果进行排序,但我仍然希望在第一页上点击。下一部分是“你认识到搜索结果是相关的吗?”可悲的是,除了经验之外,没有什么可以帮助你解决这个问题。不过,首先要谷歌搜索你的标题。
0赞 Petri Hirvonen 10/19/2022
感谢您@user4581301的提示。我尝试了各种与编译相关的搜索词,包括、标头、模板和 NetBeans,但没有想到尝试我的标题。是的,识别和理解某些结果有时非常困难,特别是因为 C++ 兔子洞似乎是 deeep。

答: 暂无答案