0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C++】クラステンプレートのファイル分割方法 (Visual Studio 2022)

Last updated at Posted at 2024-11-25

はじめに

たとえばこういうクラステンプレートのコードがあるとします。

TestClass.h

#pragma once
#include <iostream>

template <typename T>
class TestClass
{
public:
    TestClass(T num) : Num(num) {}

public:
    T SayNum() const
    {
        std::cout << "Num: " << Num << std::endl;
        return Num;
    }

private:
    T Num;
};

main.cpp

#include "TestClass.h"

int main(void)
{
	TestClass<int> intTest(10);
	intTest.SayNum();

	return 0;
}

出力

Num: 10

正常に動作しました。
これをいつものように.hに.cppにファイル分割してみようと思いますが、

TestClass.h

#pragma once

template <typename T>
class TestClass
{
public:
    TestClass(T num);

public:
    T SayNum() const;

private:
    T Num;
};

TestClass.cpp

#include <iostream>
#include "TestClass.h"

template <typename T>
TestClass<T>::TestClass(T num) : Num(num) {}

template <typename T>
T TestClass<T>::SayNum() const
{
    std::cout << "Num: " << Num << std::endl;
    return Num;
}

main.cpp

#include "TestClass.h"

int main(void)
{
    TestClass<int> intTest(10);
    intTest.SayNum();

    return 0;
}

どうなるのか、実行してみましょう。

image.png

どのファイルにもエラーが出ていませんが、未解決の外部シンボルエラーが出ました。

テンプレートの特性上、コンパイル時にインスタンス化されます。
TestClassが使用されるときにSayNumの実装が必要ですが、cppに実装部があるだけではリンク時に解決できないためリンクエラーが発生してしまうということですね。

更に詳細なことは割愛するとして、常に.hの中に書くわけにはいかないですよね。
プロジェクトが巨大化すればするほどコードの可読性が下がりかねません。

ではどのように分割すればよいのか、
私が普段行っているファイル分割の方法を説明します。

ファイル分割方法

TestClass.h

#pragma once

template <typename T>
class TestClass
{
public:
    TestClass(T num);

public:
    T SayNum() const;

private:
    T Num;
};

#include "TestClass.tpp" // TestClass.hppでも可

TestClass.tpp (TestClass.hpp)

#include <iostream

template<typename T>
TestClass<T>::TestClass(T num) : Num(num)
{
}

template <typename T>
T TestClass<T>::SayNum() const
{
    std::cout << "Num: " << Num << std::endl;
    return Num;
}

main.cpp

#include "TestClass.h"

int main(void)
{
	TestClass<int> intTest(10);
	intTest.SayNum();

	return 0;
}

.hの最後に実装部分をincludeします。
この方法が一番わかりやすくて自分はよく使います。

注意点は.cppとした後に.hppや.tppとすると、このようにC/C++コンパイラとなっています。
image.png

なのでここを、

image.png
とする必要があります。

さいごに

明示的に.cppの後ろにtemplate class TestClass<int>;とやる方法などがありますが、
汎用性が下がり、テンプレートじゃなくていいじゃんとなるのでおススメしません。

0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?