3
class A {
public:
    template<typename T> void func(size_t n, T values[]) { ... }
};

class B : public A {
public:
    void func(size_t n, uint32_t values[]) { ... }
};

このコードを呼び出すときに、関数が関数テンプレートよりも優先されB::func() ないのはなぜですか?A::func()

uint32_t values[5];
A* obj = new B();
obj->func(5, values);
4

4 に答える 4

6

2つの理由 -

  1. C++ では、基本クラス関数が virtual とマークされている場合にのみ、メンバー関数は基本クラス メンバー関数をオーバーライドします。それ以外の場合、C++ はこの 2 つを、たまたま同じ名前を持つ独立した関数として扱います。これは、関数が基本クラスの関数をアトミックにオーバーライドする Java とは対照的です。

  2. C++ では、テンプレート メンバー関数を仮想としてマークすることはできません。これは、C++ テンプレート インスタンス化システムと組み合わせて、最も一般的に使用される仮想関数 (vtables) の実装が原因の 1 つです。C++ は、異なる型引数に対する同じテンプレートのすべてのインスタンス化を個別の関数として扱い、これらのインスタンス化を遅延して生成します。これは、vtable 実装の問題です。vtable では、クラス内のさまざまな仮想関数の数をコンパイル時に静的に決定し、それらの順序付けを行う必要があるためです。テンプレート仮想関数は、クラス内の仮想関数の数と順序が不明であることを意味するため、C++ ではこれが許可されていません。

于 2011-01-01T20:08:10.347 に答える
1

func型のオブジェクト/ポインター/参照を呼び出すと、仮想ではないためAA::funcが呼び出されfuncます (仮想ではないため、それはテンプレート関数です)。

本当にコードをテストしましたか?

于 2011-01-01T20:05:04.057 に答える
0

A::func()は として宣言されていないため、コンパイラは実行時virtualに呼び出す必要のある仮想テーブルやその他のコードを生成しません。B::func()テンプレートとは関係ありません。

于 2011-01-01T20:04:37.817 に答える
0

B::func は A::func のオーバーロードではなく、何をしても決してオーバーロードされないためです。A::func virtual を宣言しようとさえしないでください。何をしようとしても、できません。静的ポリモーフィズムと動的ポリモーフィズムは、C++ では混在しません。

ポインターが A* ではなく B* を指している場合、そのバージョンが呼び出されることが予想されます。

于 2011-01-01T20:08:17.533 に答える