0

一般的な AVL 実装を http://sourceforge.net/projects/standardavl/files/standardavl/0.1/からダウンロードしました。

このプロジェクトのメイクファイルは、コードを正しくコンパイルします。コンパイラは次の出力を生成します。

g++ -pedantic -Wall -O3 -c standardavl.cpp -o standardavl.o
g++ -pedantic -Wall -O3 -c Point.cpp -o Point.o
g++ -o standardavl  standardavl.o Point.o
g++ -o genpoints genpoints.o Point.o

makefile は「standardavl.cpp」のみをコンパイルします。standartavl には「AvlTree.h」が含まれており、このファイルには「AvlTree.cpp」が含まれているためです。

標準avl.cpp

#include "AvlTree.h"
#include "Point.h"
(...)

AvlTree.h

(...)
#include "AvlTree.cpp"

私のプロジェクトでは、ファイル AvlTree.h から最後の行 (#include "AvlTree.cpp") を削除し、そのファイルを個別にコンパイルしました。ファイル「standardavl.cpp」も使用しません。ファイル Point.h を KeyPair.h に変更し、そこにすべての演算子を実装しました。

私のコンパイラは次の出力を生成します。

g++ -pedantic -Wall -O3 -c -o ../lib/CPUTimer.o ../lib/CPUTimer.cpp -I. -I../lib 
g++ -pedantic -Wall -O3 -c -o ../lib/AvlTree.o ../lib/AvlTree.cpp -I. -I../lib 
g++ -pedantic -Wall -O3 -c -o ../lib/keypair.o ../lib/keypair.cpp -I. -I../lib 
g++ -pedantic -Wall -O3 -c -o graph.o graph.cpp -I. -I../lib 
g++ -pedantic -Wall -O3 -c -o dijkstra.o dijkstra.cpp -I. -I../lib 
g++ -pedantic -Wall -O3 -o ../../q1 ../lib/CPUTimer.o ../lib/AvlTree.o ../lib/keypair.o graph.o dijkstra.o questao1.cpp -I. -I../lib 
dijkstra.o: In function 'Dijkstra::executeAvl(int)':
dijkstra.cpp:(.text+0x25d): undefined reference to 'AvlTree<KeyPair, std::less<KeyPair>, nil<KeyPair> >::AvlTree()'
(... a lot of errors like above ...)
collect2: ld returned 1 exit status
make[1]: ** [q1] Erro 1

ここで何が間違っていますか?

4

1 に答える 1

2

AvlTree.h がテンプレート クラスAvlTree<>を宣言し、AvlTree.cpp が実装を定義するとします。

別の翻訳単位 (.cpp) でテンプレート コードの実装を定義することはできません。それが使用される場所に存在する必要があります。それが彼らがそれをヘッダーに含めた理由です。インクルードする .cpp ファイルに実装を配置することは、.h ファイルを簡潔に保つための設計上の選択にすぎません。

(技術的には、テンプレート定義を別の翻訳単位に入れることができますが、使用するテンプレート引数に対して明示的にインスタンス化する必要があります。それはあなたがやりたいことではないと思います。)

于 2011-05-16T23:58:44.460 に答える