C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++におけるアーリーバインディングとレイトバインディングの違いを徹底解説

本記事では、C++における「アーリーバインディング(早期結合・静的結合)」と「レイトバインディング(遅延結合・動的結合)」の違いについて、サンプルコードを交えながら分かりやすく解説します。

バインディング(結合)とは、識別子(変数名や関数名)を実際のメモリアドレスへ変換するプロセスのことです。すべての変数と関数に対してこの結合が行われます。特に関数の場合は、コンパイラが関数呼び出しを適切な関数定義と一致させる処理を指します。この結合は、コンパイル時に行われるか、実行時に行われるかのいずれかであり、それぞれがアーリーバインディングとレイトバインディングに対応します。

アーリーバインディング(早期結合)とは

アーリーバインディングはコンパイル時ポリモーフィズム(静的多態性)とも呼ばれます。関数呼び出しに対して、コンパイル時に直接アドレスが関連付けられるため、実行時のオーバーヘッドがなく高速に動作します。関数オーバーロードやテンプレートがその代表例です。

ただし注意点があります。基底クラスのポインタで派生クラスのオブジェクトを指す場合、メンバ関数が virtual 宣言されていなければ、ポインタの型(基底クラス型)を基準に関数が決定されます。次の例で確認してみましょう。

コード例

#include<iostream>
using namespace std;

class Base {
public:
    void display() {
        cout << "In Base class" << endl;
    }
};

class Derived : public Base {
public:
    void display() {
        cout << "In Derived class" << endl;
    }
};

int main(void) {
    Base *base_pointer = new Derived;
    base_pointer->display();
    return 0;
}

実行結果

In Base class

ポインタは Derived クラスのオブジェクトを指していますが、display() が仮想関数ではないため、コンパイル時にポインタの型である Base クラスの display() へと結合されます。そのため「In Base class」と表示されるのです。

レイトバインディング(遅延結合)とは

レイトバインディングは実行時ポリモーフィズム(動的多態性)です。この方式では、コンパイラが実行時にオブジェクトの実際の型を判別するコードを挿入し、その情報をもとに関数呼び出しを正しい関数定義と一致させます。これは仮想関数(virtual キーワード)を使うことで実現され、内部的には vtable(仮想関数テーブル)と vptr(仮想テーブルポインタ)という仕組みによって支えられています。

コード例

#include<iostream>
using namespace std;

class Base {
public:
    virtual void display() {
        cout << "In Base class" << endl;
    }
};

class Derived : public Base {
public:
    void display() {
        cout << "In Derived class" << endl;
    }
};

int main() {
    Base *base_pointer = new Derived;
    base_pointer->display();
    return 0;
}

実行結果

In Derived class

display() に virtual を付けたことで、実行時にオブジェクトの実際の型(Derived クラス)が判定され、Derived クラスの display() が呼び出されました。これがレイトバインディングによる多態性の動作です。

両者の違いのまとめ

項目アーリーバインディングレイトバインディング
結合のタイミングコンパイル時実行時
別名静的結合/早期結合動的結合/遅延結合
ポリモーフィズムの種類コンパイル時ポリモーフィズム実行時ポリモーフィズム
主な実現手段関数オーバーロード、テンプレート仮想関数(virtual)
実行速度高速わずかなオーバーヘッドあり
柔軟性低い高い

パフォーマンスが重視される場面ではアーリーバインディングが有利ですが、基底クラスのインターフェースを通じて異なる派生クラスの振る舞いを実行時に切り替えたい場合は、仮想関数によるレイトバインディングが不可欠です。用途に応じて両者を使い分けることが、質の高いC++プログラミングへの第一歩となります。

  1. C++のクラスとオブジェクトとは?基本概念と定義方法を初心者向けに解説

    クラスは、C++における最も重要な機能の一つです。オブジェクト指向プログラミング(OOP)の中核となる概念を実現するためのユーザー定義型であり、データ変数と、そのデータを操作するための関数を1つのパッケージにまとめることができます。クラスは、オブジェクトの設計図(仕様)を提供する役割を担います。クラスの定義方法クラスの定義は「class」キーワードから始まり、その後にクラス名を記述します。続いて、波括弧({})で囲まれたクラス本体を定義し、末尾に必ずセミコロン(;)を付けます。C++におけるクラス定義の基本的な例は以下の通りです。class Student {   &nbs

  2. C++のフレンド関数とフレンドクラスの基本を解説

    C++におけるフレンド関数(friend function)とは、クラスのスコープ外で定義される関数でありながら、そのクラスのすべてのprivateメンバーおよびprotectedメンバーにアクセスする権限を持つ特別な関数です。フレンド関数のプロトタイプ(宣言)はクラス定義の中に記述しますが、あくまで「友達」として扱われるだけであり、クラスのメンバー関数にはなりません。この点は重要なポイントです。フレンドとして指定できるものフレンドとして宣言できるのは、以下のようなものです。通常の関数関数テンプレート他のクラスのメンバー関数クラス全体(この場合、そのクラスのすべてのメンバーがフレンドになります