0

静的関数呼び出しを必要とする呼び出し環境を変更せずに継承を使用するようにテンプレート クラスを書き直しますが、静的関数を仮想にすることはできません。

この質問は、C++ コーディング テストで見つけました。実際、この質問はそれほど明確に述べられておらず、これまでのところ解決策がありません。あいまいで申し訳ありません。誰でもこの質問をよりよく理解できるように。以下は私の個人的な解釈です。私の誤解を指摘していただきありがとうございます。

このテンプレート クラスは、サーバー側でカプセル化されたライブラリであり、静的関数などの一部の API はクライアント側で呼び出されます。ただし、静的関数を仮想にすることはできません。つまり、静的関数には動的境界 (オーバーライド) は許可されません。

  1. テンプレート クラスを書き直そうとすると、このクラスは継承を使用します。したがって、このクラスには派生クラスがあります。しかし、API 呼び出し環境を変更したくありません。つまり、サーバー側のコードをアップグレードする予定ですが、クライアント側のコードを変更したくありません。

  2. テンプレートクラスを書き換えるために、継承を使用してみてください。しかし、API 呼び出し環境を変更したくありません。つまり、サーバー側のコードをアップグレードする予定ですが、クライアント側のコードを変更したくありません。

1 と 2 のどちらが正しい解釈かはわかりません。しかし、私はより 1 に傾いています。私の意見では、この質問は主に次の概念をテストします。

  1. サーバーサイドでのコードメンテナンス
  2. ファクトリーメソッドを中心としたデザインパターン
  3. クラス継承で静的関数をオーバーライドするためのトリック

サーバー側の元のコード:

#include<iostream>

using namespace std;

template<class T>
class Base
{
    public:
        Base(){}
        Base(T B):m_B(B){}
        virtual ~Base(){}

        // Static method
        static void speak()
        {
            cout << "I am Base class" << endl;
        }

    private:
        T m_B;

};


template<class T>
class Derived: public Base<T>
{
    public:
        Derived(){}
        Derived(T B, T D): Base<T>(B), m_D(D){}
        ~Derived(){}

        // Static method
        static void speak()
        {
            cout << "I am Derived class" << endl;
        }

    private:
        T m_D;

};

クライアント側の呼び出し環境:

int main(int argc, char* argv[])
{
    Base<int> *bPtr = new Derived<int>(5, 10);
    bPtr->speak();
    delete bPtr;
    return 0;
}

出力:

私は基本クラスです

(明らかに、静的関数のオーバーライドはありません)

/////////////////////////////////////////////// /////////////////////////////

サーバー側でコードを書き直しました:

#include<iostream>

using namespace std;

template<class T>
class Base
{
    public:
        Base(){}
        Base(T B):m_B(B){}
        virtual ~Base(){}

        // Static method
        static void speak()
        {
            cout << "I am Base class" << endl;
        }
        // Non-static method
        virtual void call_speak()
        {
            speak();    
        }   
    private:
        T m_B;

};


template<class T>
class Derived: public Base<T>
{
    public:
        Derived(){}
        Derived(T B, T D): Base<T>(B), m_D(D){}
        ~Derived(){}

        // Static method
        static void speak()
        {
            cout << "I am Derived class" << endl;
        }
        // Non-static method
        void call_speak()
        {
            speak();    
        }   
    private:
        T m_D;

};

template<class T>
class Factory
{
    public:
        // Return a base instance
        static Base<T>* getInstance(T B)
        {
            Base<T> *bPtr = new Base<T>(B);
            return bPtr;
        }

        // Return a derived instance
        static Base<T>* getInstance(T B, T D)
        {
            Base<T> *bPtr = new Derived<T>(B, D);
            return bPtr;
        }
};

クライアント側の呼び出し環境:

int main(int argc, char* argv[])
{
    Base<int> *bPtr = Factory<int>::getInstance(5, 10);
    bPtr->speak();
    bPtr->call_speak();
    delete bPtr;
    return 0;
}

出力:

私は基本クラスです

私は派生クラスです

私の修正:

  1. 静的関数を「オーバーライド」するには、トリックとして静的関数を呼び出す仮想関数を追加します。
  2. ファクトリ メソッドを使用して、インスタンスの作成をクライアント側から隠します。

しかし、そのような変更が呼び出し環境を変更しないという要件を満たすことができるかどうかはわかりません。クライアント側でAPI呼び出しを変更するためです。私の努力に基づいて、それが私の最善の解決策です。コメントと改善を大いに感謝します。

4

0 に答える 0