0Pricing
C++ Academy · レッスン

静的ポリモーフィズム

仮想関数呼び出しのオーバーヘッドを避けます

「静的ポリモーフィズム」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。

2種類のポリモーフィズム

C++は2種類のポリモーフィズムをサポートしています。

  • 動的:仮想関数を仮想テーブル経由で実行時に解決します
  • 静的:テンプレートやCRTPをコンパイル時に解決します

静的ポリモーフィズムは、柔軟性と引き換えに速度を得ます。

virtualのコスト

virtual関数の呼び出しでは、仮想テーブルを介した間接ジャンプが必要です。コンパイラは通常これをインライン化できないため、多くの最適化が妨げられます。

#include <iostream>

struct Shape {
    virtual double area() const = 0;
    virtual ~Shape() = default;
};

struct Square : Shape {
    double s;
    Square(double x) : s(x) {}
    double area() const override { return s * s; }
};

int main() {
    Shape* p = new Square(3);
    std::cout << p->area() << "\n";
    delete p;
    return 0;
}

CRTPによる静的ディスパッチ

CRTPでは、基底クラスがコンパイル時のキャストを通じて派生クラスのメソッドを直接呼び出すため、コンパイラはすべてをインライン化できます。

#include <iostream>

template <typename T>
struct Shape {
    double area() const { return static_cast<const T*>(this)->area(); }
};

struct Square : Shape<Square> {
    double s;
    Square(double x) : s(x) {}
    double area() const { return s * s; }
};

int main() {
    Square sq(3);
    std::cout << sq.area() << "\n";
    return 0;
}

フォワーダーの命名

基底クラスと派生クラスの両方がareaを定義する場合、基底クラスのフォワーダーにはcomputeのような別の名前を付け、派生クラスの実装を明確に呼び出せるようにします。

#include <iostream>

template <typename T>
struct Shape {
    double compute() const { return static_cast<const T*>(this)->area(); }
};

struct Circle : Shape<Circle> {
    double r;
    Circle(double x) : r(x) {}
    double area() const { return 3.14159 * r * r; }
};

int main() {
    Circle c(2);
    std::cout << c.compute() << "\n";
    return 0;
}

静的ポリモーフィズムとしてのテンプレート

通常の関数テンプレートも静的ポリモーフィズムです。必要なインターフェースを提供する任意の型に対して同じコードが機能します(コンパイル時のダックタイピング)。

#include <iostream>

struct Dog { void speak() const { std::cout << "Woof\n"; } };
struct Cat { void speak() const { std::cout << "Meow\n"; } };

template <typename Animal>
void make_speak(const Animal& a) { a.speak(); }

int main() {
    make_speak(Dog{});
    make_speak(Cat{});
    return 0;
}

型が既知の場合

静的ポリモーフィズムは、具体的な型がコンパイル時に既知である場合にのみ適用できます。異なる型のオブジェクトを1つのコンテナに格納し、実行時に動作を選択する必要がある場合は、依然として仮想関数が必要です。

異種コンテナは使えない

Shape<Square>とShape<Circle>は無関係な型であるため、共通の基底クラスとして同じstd::vectorに格納することはできません。これが静的ポリモーフィズムの根本的な制約です。

パフォーマンス上の利点

ディスパッチされる呼び出しをインライン化すると、コンパイラーは定数を畳み込み、関数呼び出しのオーバーヘッドを完全に排除できます。単一の既知の型に対するタイトなループでは、静的ポリモーフィズムによって大幅に高速化できる場合があります。

#include <iostream>

template <typename T>
struct Op {
    int apply(int x) const { return static_cast<const T*>(this)->apply(x); }
};

struct Doubler : Op<Doubler> {
    int apply(int x) const { return x * 2; }
};

int main() {
    Doubler d;
    int sum = 0;
    for (int i = 0; i < 5; ++i) sum += d.apply(i);
    std::cout << sum << "\n";
    return 0;
}

両方を組み合わせる

ホットパスにはCRTPを使用し、型消去が必要な場合には薄い仮想ラッパーを使用できます。これにより、重要な部分では速度を、必要な部分では柔軟性を得られます。

静的インターフェースチェック

派生クラスが必要なメソッドの実装を忘れた場合、実行時ではなく、基底クラスのフォワーダーがインスタンス化されるコンパイル時にエラーが発生します。

#include <iostream>

template <typename T>
struct Greeter {
    void greet() const { static_cast<const T*>(this)->hello(); }
};

struct English : Greeter<English> {
    void hello() const { std::cout << "Hello\n"; }
};

int main() {
    English{}.greet();
    return 0;
}

適切なツールの選択

次の場合は静的ポリモーフィズムを使用します。

  • 型がコンパイル時に既知である
  • パフォーマンスが重要である
  • 共通の実行時基底型が必要ない

それ以外の場合は、明快さと柔軟性を重視して仮想関数を選ぶとよいでしょう。

確認問題

静的ポリモーフィズムの主なトレードオフを選んでください。

まとめ

静的ポリモーフィズムと動的ポリモーフィズムを比較しました。

  • 仮想関数 = 実行時ディスパッチ、vtable、異種コンテナ
  • CRTP/テンプレート = コンパイル時ディスパッチ、インライン化可能、高速
  • 静的ポリモーフィズムには、コンパイル時に既知の型が必要
  • 柔軟性とパフォーマンスの必要性に基づいて選択する

よくある質問

「静的ポリモーフィズム」レッスンは無料ですか?

はい。「静的ポリモーフィズム」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。

「静的ポリモーフィズム」で何を学びますか?

仮想関数呼び出しのオーバーヘッドを避けます ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C++ Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「静的ポリモーフィズム」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC++ Academyレッスンでコードを書いて実行できますか?

はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. CRTPイディオム
  2. 静的ポリモーフィズム
  3. CRTPによるミックスイン
  4. CRTPを使うタイミング
← C++ Academyに戻る