3

Templateテンプレート値を格納できるC++クラスを作成しようとしています。ただし、テンプレート値のタイプを知る前に、このクラスへのポインターを作成する必要があります。これを行うためにBase、テンプレートクラスが継承する抽象クラスを作成しました。へのポインタを作成しBase、それらが割り当てられるときに、を使用しますbasePtr = new Template<TYPE>

ここでの問題は、に値を割り当てることですTemplate。私がそうすることを考えることができるすべての方法(私はオーバーロードされた代入演算子を使用したいと思います)は、正式なパラメーターとしてテンプレートデータ型を持つメソッドを必要とします。Templateオブジェクトにはポインタを介してのみアクセスできるためBase、で仮想関数を作成する必要がありますBase。ただし、仮想メソッドにテンプレートデータ型を含めることはできません。また、Base署名の仮想メソッドは、のメソッドの仮想メソッドと一致する必要がありTemplateます。

これが私がしようとしていることの例です:

class Base {
    public:
        /* THIS IS ILLEGAL - can't have template virtual method
        template <class V>
        virtual void operator =(const V& newValue) = 0;
        */
};

template <class ValueType>
class Template : public Base {
    private:
        ValueType *value;
    public:
        void operator =(const ValueType& newValue) {
            *value = newValue;
        }
};

int main() {
    Base *theObject;                  // Datatype for template not known 
    theObject = new Template<string>; // At this point, it will be known

    // NOW, THIS DOESN'T WORK - no virtual assignment overload in Base
    *theObject = "Hello, world!";

    return 0;
}

私がこれを完全に間違った方法で行っている場合、そして私の方法が愚かである場合、私は謝罪します-これは本当のOODへの私の最初の進出です。私が見ないこの問題を回避する方法はありますか?Base次のように、代入演算子をさまざまな入力タイプでオーバーロードする純粋仮想関数の長いリストを作成できることはわかっています。

virtual void operator =(const string& newValue) = 0;
virtual void operator =(const int& newValue) = 0;
virtual void operator =(const long& newValue) = 0;
...

しかし、ユーザーがカスタムクラスオブジェクト(または、より可能性が高いのはそれらのオブジェクトへのポインター)をに挿入できるようにしたいのでTemplate::value、上記の方法で実行できる方法はありません。

4

2 に答える 2

1

達成しようとしていることを実行する1つの方法は、Boost.Any(よく知られているヘッダーのみのライブラリ)を使用することです。以下はデモンストレーションです。コードは段階的にコメントされているので、理解できるはずです。これが実際の例です。

#include <stdexcept>       // Standard header for exception classes
#include <string>          // Standard header for std::string
#include <boost/any.hpp>   // The Boost.Any library header
#include <iostream>        // This program prints some output

class Base
{
public:
    virtual void operator = (boost::any val) = 0;
    //                       ^^^^^^^^^^
    //                       This can hold (almost) "any" value

    // You need a virtual destructor if you want to delete objects
    // of subclasses of this class through a pointer to this class!
    virtual ~Base() { }
};

template <class ValueType>
class Template : public Base
{
private:
    ValueType value;
//  ^^^^^^^^^
//  I do not see why using a pointer in this case. Manual memory
//  management just complicates things. However, if your really
//  need to do it and your really know what you're doing, go ahead.
//  Just remember to delete your pointer at destruction and not to
//  dereference it before it points to an allocated object (in your
//  original text, both of these things are NOT done correctly).
public:
    virtual void operator = (boost::any val)
    {
        // Attempt a cast to detect if the value we are trying to
        // assign to this object is of the appropriate type...
        ValueType* pVal = boost::any_cast<ValueType>(&val);
        if (pVal == nullptr)
        {
            // ...it is not! Throw an exception...
            throw std::logic_error("Incompatible type");
        }

        // The value is OK: assign it...
        value = *pVal;
    }
};

int main()
{
    Base *theObject;
    theObject = new Template<std::string>;

    try
    {
        // This assignment will succeed...
        // Wrapping the string literal in a std::string object is necessary
        // because boost::any cannot be initialized from an array (and in C++
        // string literals are arrays of characters).
        *theObject = std::string("Hello, world!");

        // This assignment will fail!
        *theObject = 1;
    }
    catch (std::logic_error const& e)
    {
        // Handle the exception...
        std::cout << e.what();
    }

    delete theObject; // <=== DON'T FORGET THIS!

    return 0;
}
于 2013-02-28T01:56:41.177 に答える
0

boost::anyのように聞こえます。奇妙な継承階層は必要ありません。任意のタイプ(特定の制限付き)を独自に格納できます。

今私が心配しているのは、あなたがどのようにあなたの価値を再び取り戻すことを計画しているのかということです。コードは、そのセルにint、std :: string、またはこれまで聞いたことのない他のユーザー定義型が含まれているかどうかをどのように判断しますか。タイプがリストされていません...)?

于 2013-02-28T02:12:38.160 に答える