4

子クラスによって実装される純粋仮想メソッドを持つC++のクラスのベースを定義しようとしています。

基本クラスの基本型のsetter関数とgetter関数を定義したいのですが、派生クラスでgetterとsetterの基本型を判別できるようにしたいと思います。たとえば、私の基本クラスは次のようになります。

    class Value
    {
    public:
        Value();
        template <class T>;
        virtual T getValue() = 0;
        virtual void setValue(T val) = 0;
    }

私の子クラスは次のようになります。

    class IntValue : public Value
    {
    public:
        IntValue();
        template <class T>
        T getValue() {return _val};
        void setValue(T val) {_val = val};
    private:
        int _val;
    }

もちろん、上記のコードは機能しません。これを達成する方法について何かアイデアはありますか?前もって感謝します。

4

3 に答える 3

5

問題を正しく理解した場合は、コードを次のように書き直してください。

template <class T>
class Value
{
public:
    Value();
    virtual T getValue() = 0;
    virtual void setValue(T val) = 0;
};


class IntValue : public Value<int>
{
public:
    IntValue();

    int getValue() {return _val;}
    void setValue(int val) {_val = val;}
private:
    int _val;
};

動作するはずです

于 2012-05-30T17:04:04.273 に答える
4

あなたが求めていることは不可能です。(またはコンパイラが使用している可能性のある同様の構造)で適切なエントリを生成するためにvtbl、コンパイラは、基本クラスで具体的にどのエントリが必要になるかを知る必要があります。派生クラスで別の型を返すだけで、基本クラスがそのようにそれについて「知っている」ことを期待することはできません。基本クラスの関数テンプレートの定義を変更する必要があるためです。

(関数テンプレートではなく)クラステンプレートを使用して基本クラスのそのような変更を行う方法の例は、 J_Dの回答に示されていますが、それでも問題の説明と正確には一致しません。を作成し、それを多形的に扱うことができます。Value

C ++テンプレートは、基本的にタイプで「ファンシーパンツを見つけて置換」します。コンパイラが関数テンプレートをインスタンス化すると、タイプ名が置換されたプレーン関数が生成されます。これは、C#またはJavaの「ジェネリック」とは大きく異なることに注意してください。これらは完全に異なり、ランタイムサポートと間接化のレイヤーに依存して同様の効果を実現します。(ただし、この「検索と置換」は、Cプリプロセッサマクロとは異なり、優先順位規則などを尊重することに注意してください:))

あなたが本当にそれについても考えるならば、このパターンは意味がありません。これは、クライアント側では実際にどのように見えるでしょうか?

class Value
{
public:
    Value();
    //Imagine if this were possible...
    template <class T>;
    virtual T getValue() = 0;
    virtual void setValue(T val) = 0;
}

class IntValue : public Value
{
public:
    IntValue();
    int getValue() {return _val};
    void setValue(int val) {_val = val};
private:
    int _val;
}

class FloatValue : public Value
{
public:
    FloatValue();
    float getValue() {return _val};
    void setValue(float val) {_val = val};
private:
    float _val;
}

次に、このクラスを使用します。

void example(Value * ptr)
{
    //What could you possibly say the type of "bar" is? There's no type that works!
    ???? bar = ptr->getValue();
    delete ptr;
}

int main()
{
    example(new IntValue());
    example(new FloatValue());
}

そのため、これが許可されたとしても、あまり意味がありません。あなたはいつも常にダウンキャストしvirtualなければならないでしょう、それはキーワードがとにかく無意味であることを意味するでしょう。

于 2012-05-30T17:05:37.340 に答える
1

@Billy ONealがクラステンプレートについて言ったことを拡張すると、これはあなたの目的に役立つかもしれません:

template<typename Type>
class Value
{
public:
    virtual Type getValue() = 0;
};

class IntValue : public Value<int>
{
public:
    IntValue(int value)
        : m_value(value)
    {
    }

    int getValue()
    {
        return m_value;
    }

private:
    int m_value;
};
于 2012-05-30T17:08:30.240 に答える