katapedia
  • README
  • doc
    • Ansible
    • Assert
    • Astah
    • Autohotkey
    • CI
    • C_Cpp
    • CentOS6x系でhttp認証に失敗する
    • Chef
    • Clipboard
    • コーディング
    • Configure
    • Console2_NYAOS
    • Debian系RedHat系の違い
    • DesignDoc目次サンプル
    • Docker
    • Doxygenコメント規約
    • Eclipse
    • Excel
    • FAQ
    • Footer
    • Git
    • GitBucket
    • GitBucketとJenkins連携
    • GitBucketとRocketChat連携
    • GitHub
    • GitLab
    • Gitで大量のファイルの中から必要ファイルのみをaddする方法
    • GitのGUI比較
    • Gitのリポジトリがでかくなったときの削減の昔のやり方
    • Gitワークフロー
    • Go
    • Googletest
    • Gradle
    • Grafana
    • Groovy
    • Haroopad
    • Haskell
    • Htmlpdfに直リンクする(ダウンロードしない)方法
    • IT業界
    • Java
    • Javascript
    • Javascriptrライブラリ・フレームワーク一覧
    • Jenkins
    • JetBrains_IDE
    • Linux
    • Linux Command
    • Linux Distribution
    • Makefile
    • Maven
    • MicrosoftProject
    • NoSQL
    • Omniauthによるアカウント統合
    • Outlook
    • PHP
    • Prometheus_Loki
    • Python
    • RDB
    • Redmine
    • RedmineDドライブへの保存
    • Redmineアップデート
    • Redmineプラグイン
    • Redmineメール通知
    • Redmine文字化け
    • Ruby
    • Rust
    • R言語
    • SVN
    • Sidebar
    • Solaris
    • Staticまとめ
    • Terraform
    • Thinkpad
    • Tmux
    • ToDoリスト
    • UML
    • Vagrant
    • Vim/Neovim
    • VirtualBox
    • Visio
    • Webアプリケーション
    • Webサーバ
    • Webブラウザ
    • Webブラウジング
    • Webページ備忘録
    • Windows
    • Word
    • Zabbix
    • Zsh
    • C#
    • dotfiles
    • html_css
    • Lua
    • sonarqube
    • terminal
    • tweetまとめ
    • xrdp
    • お預り証サンプル
    • その他Webサービス
    • その他ツール
    • よく使う英語
    • アジェンダサンプル
    • アジャイル宣言
    • アンチパターン
    • インシデント
    • エディタ・IDE
    • エンジニアリングスキル
    • オンプレミスサーバ管理
    • オープンソースライセンス
    • キックオフミーティング
    • コミットメッセージでよく使う英語
    • サーバデータ移行
    • サーバ環境構築
    • シェルスクリプト
    • セキュリティ
    • ソフトウェア開発
    • チャットツール
    • チーム構築
    • ツール調査履歴
    • テスト
    • デザイン
    • デザインパターン
    • ドキュメント
    • ネットワーク
    • ノート
    • バージョン番号
    • ビジネスモデル
    • プラクティス一覧
    • プラグイン調査
    • プログラマがやってはいけない97のこと
    • プログラミングテクニック
    • プログラム
    • プログラムエラー集
    • プロジェクトマネージメント
    • プロダクトマネージメント
    • ヘルプ文
    • ライフハック
    • リソース設計
    • リバースエンジニアリングツール
    • リリースノート
    • リリースノートサンプル1
    • リンク
    • レビュー
    • 人月の神話
    • 人間のあれこれ
    • 仕事のあれこれ
    • 会議
    • 作業報告項目サンプル
    • 例外処理
    • 勉強
    • 名言・教訓
    • 品質管理
    • 教育
    • 数学
    • 文書レビュー観点
    • 朝会
    • 未来技術
    • 林檎の木のものを持ってきた
    • 正規表現
    • 物理
    • 知識データベース
    • 紛らわしい・似たような用語
    • 経営
    • 経済
    • 自作template_class_でundefined_reference_to
    • 要求分析・要件定義
    • 見積もり
    • 設計
    • 評価
    • 認証
    • 議事録サンプル
    • 運用・保守
    • 開発インフラ
    • 開発環境
    • 開発計画
    • 関数名でよく使われる英単語
    • 関数命名規約
    • 関数型言語
    • 雑多メモ
    • 面接
Powered by GitBook
On this page
  • 自作template class でundefined reference to
  • ifndef NODO_COLAYPILA_H
  • define NODO_COLAYPILA_H
  • include
  • include "nodo_colaypila.h"
  • include
  • ifndef COLA_H
  • define COLA_H
  • include "nodo_colaypila.h"
  • endif // COLA_H
  • include "cola.h"
  • include "nodo_colaypila.h"
  • include
  • include
  • include "cola.h"
  • include "nodo_colaypila.h"
  1. doc

自作template_class_でundefined_reference_to

自作template class でundefined reference to

.cppにて使用されtる型を明示するか、.hに直接記述するかすること

“Undefined reference to” template class constructor

up vote

12

down vote

favorite

11

I have no idea why this is happenning, since I think I have everything properly declared and defined.

>

I have the following program, designed with templates. It's a simple implementation of a queue, with the member functions "add", "substract" and "print".

>

I have defined the node for the queue in the fine "nodo_colaypila.h":

ifndef NODO_COLAYPILA_H

define NODO_COLAYPILA_H

include

template class cola;

template class nodo_colaypila

{

T elem;

nodo_colaypila* sig;

friend class cola;

public:

nodo_colaypila(T, nodo_colaypila*);

};

</code></pre>

Then the implementation in "nodo_colaypila.cpp"

include "nodo_colaypila.h"

include

template nodo_colaypila::nodo_colaypila(T a, nodo_colaypila* siguiente = NULL)

{

elem = a;

sig = siguiente;//ctor

}

</code></pre>

Afterwards, the definition and declaration of the queue template class and its functions:

"cola.h":

ifndef COLA_H

define COLA_H

include "nodo_colaypila.h"

template class cola

{

nodo_colaypila* ult, pri;

public:

cola();

void anade(T&);

T saca();

void print() const;

virtual ~cola();

};

endif // COLA_H

</code></pre>

"cola.cpp":

include "cola.h"

include "nodo_colaypila.h"

include

using namespace std;

template cola::cola()

{

pri = NULL;

ult = NULL;//ctor

}

template void cola::anade(T& valor)

{

nodo_colaypila * nuevo;

if (ult)

{

nuevo = new nodo_colaypila (valor);

ult->sig = nuevo;

ult = nuevo;

}

if (!pri)

{

pri = nuevo;

}

}

template T cola::saca()

{

nodo_colaypila * aux;

T valor;

aux = pri;

if (!aux)

{

return 0;

}

pri = aux->sig;

valor = aux->elem;

delete aux;

if(!pri)

{

ult = NULL;

}

return valor;

}

template cola::~cola()

{

while(pri)

{

saca();

}//dtor

}

template void cola::print() const

{

nodo_colaypila * aux;

aux = pri;

while(aux)

{

cout << aux->elem << endl;

aux = aux->sig;

}

}

</code></pre>

Then, I have a program to test these functions as follows:

"main.cpp"

include

include "cola.h"

include "nodo_colaypila.h"

using namespace std;

int main()

{

float a, b, c;

string d, e, f;

cola flo;

cola str;

a = 3.14;

b = 2.71;

c = 6.02;

flo.anade(a);

flo.anade(b);

flo.anade(c);

flo.print();

cout << endl;

d = "John";

e = "Mark";

f = "Matthew";

str.anade(d);

str.anade(e);

str.anade(f);

cout << endl;

c = flo.saca();

cout << "First In First Out Float: " << c << endl;

cout << endl;

f = str.saca();

cout << "First In First Out String: " << f << endl;

cout << endl;

flo.print();

cout << endl;

str.print();

cout << "Hello world!" << endl;

return 0;

}

</code></pre>

But when I build, the compiler throws errors in every instance of the template class:

>

undefined reference to `cola(float)::cola()'... (it's actually cola'<'float'>'::cola(), but this doesn't let me use it like that.)

>

And so on. Altogether, 17 warnings, counting the ones for the member functions being called in the program.

>

Why is this? Those functions and constructors WERE defined. I thought that the compiler could replace the "T" in the template with "float", "string" or whatever; that was the advantage of using templates.

>

I read somewhere here that I should put the declaration of each function in the header file for some reason. Is that right? And if so, why?

>

Thanks in advance.

>

This is a common question in C++ programming. There are two valid answers to this. There are advantages and disadvantages to both answers and your choice will depend on context. The common answer is to put all the implementation in the header file, but there's another approach will will be suitable in some cases. The choice is yours.

>

The code in a template is merely a 'pattern' known to the compiler. The compiler won't compile the constructors cola::cola(...) and cola::cola(...) until it is forced to do so. And we must ensure that this compilation happens for the constructors at least once in the entire compilation process, or we will get the 'undefined reference' error. (This applies to the other methods of cola also.)

>

Understanding the problem

>

The problem is caused by the fact that main.cpp and cola.cpp will be compiled separately first. In main.cpp, the compiler will implicitly instantiate the template classes cola and cola because those particular instantiations are used in main.cpp. The bad news is that the implementations of those member functions are not in main.cpp, nor in any header file included in main.cpp, and therefore the compiler can't include complete versions of those functions in main.o. When compiling cola.cpp, the compiler won't compile those instantiations either, because there are no implicit or explicit instantiations of cola or cola. Remember, when compiling cola.cpp, the compiler has no clue which instantiations will be needed; and we can't expect it to compile for every type in order to ensure this problem never happens! (cola, cola, cola, cola< cola > ... and so on ...)

>

The two answers are:

>

Tell the compiler, at the end of cola.cpp, which particular template classes will be required, forcing it to compile cola and cola.

Put the implementation of the member functions in a header file that will be included every time any other 'translation unit' (such as main.cpp) uses the template class.

Answer 1: Explicitly instantiate the template, and its member definitions

>

At the end of cola.cpp, you should add lines explicitly instantiating all the relevant templates, such as

>

template class cola;

template class cola;

and you add the following two lines at the end of nodo_colaypila.cpp:

>

template class nodo_colaypila;

template class nodo_colaypila;

This will ensure that, when the compiler is compiling cola.cpp that it will explicitly compile all the code for the cola and cola classes. Similarly, nodo_colaypila.cpp contains the implementations of the nodo_colaypila<...> classes.

>

In this approach, you should ensure that all the of the implementation is placed into one .cpp file (i.e. one translation unit) and that the explicit instantation is placed after the definition of all the functions (i.e. at the end of the file).

>

Answer 2: Copy the code into the relevant header file

>

The common answer is to move all the code from the implementation files cola.cpp and nodo_colaypila.cpp into cola.h and nodo_colaypila.h. In the long run, this is more flexible as it means you can use extra instantiations (e.g. cola) without any more work. But it could mean the same functions are compiled many times, once in each translation unit. This is not a big problem, as the linker will correctly ignore the duplicate implementations. But it might slow down the compilation a little.

>

Summary

>

The default answer, used by the STL for example and in most of the code that any of us will write, is to put all the implementations in the header files. But in a more private project, you will have more knowledge and control of which particular template classes will be instantiated. In fact, this 'bug' might be seen as a feature, as it stops users of your code from accidentally using instantiations you have not tested for or planned for ("I know this works for cola and cola, if you want to use something else, tell me first and will can verify it works before enabling it.").

>

Finally, there are three other minor typos in the code in your question:

>

You are missing an #endif at the end of nodo_colaypila.h

in cola.h nodo_colaypila ult, pri; should be nodo_colaypila ult, *pri; - both are pointers.

nodo_colaypila.cpp: The default parameter should be in the header file nodo_colaypila.h, not in this implementation file.

share|improve this answer

Previous経済Next要求分析・要件定義

Last updated 7 years ago