2

私の前の質問によると、引数として取るメソッドで使用できるように、 a が実際に(またはおそらく)boost::shared_ptr<A>のサブクラスであることを望みます。AA*A*

次のクラスを検討してください。

class A
{
public:
    A(int x) {mX = x;}
    virtual void setX(int x) {mX = x;}
    virtual int getX() const {return mX;}
private:
    int mX;
};

前の質問で、これを処理するために SharedA オブジェクトを作成することを提案しましたが、おそらくそうなります。

class SharedA : public A
{
public:
    SharedA(A* a) : mImpl(a){}
    virtual void setX(int x) {mImpl->setX(x);}
    virtual int getX() const {return mImpl->getX();}
private:
    boost::shared_ptr<A> mImpl;
};

テンプレートクラスを作成して、これらすべてを処理できるとしたら、それは大変なことです。

template <class T>
class Shared : public T
{
public:
    SharedT(T* t) : mImpl(t)
    {
    //What kind of crazy voodoo goes here?
    }

private:
    boost::shared_ptr<T> mImpl;
};

これがあれば (適切なコンストラクターと共にShared<T>)、次のことができます。

A* indestructo_A = new Shared<A>(new A(100));
A* indestructo_A_clone = new Shared<A>(indestructo_A);
delete indestructo_A
cout << "Indestructo-A back with a vengence!" << indestructo_A_clone.getX();

質問:

  1. これは役に立ちますか?または、特に悪いコードを扱っているコーナーケースでのみそのユーティリティが使用されます。例えば:

    void aFunctionYouHaveToUse(A* a) { /有用なアルゴリズムを実行してから/
    a を削除します。}

  2. そのようなテンプレート化されたクラスを構築することは可能ですか? (リフレクションが必要だと思いますよね?)それを構築できるとしたら、どうやって?

4

3 に答える 3

8

shared_ptr が A* への明示的なキャストを許可しないのには、本当に、非常に正当な理由があります (継承よりも良い方法がありますが、とにかく不可能です)。shared_ptr およびその他のスマート ポインターの全体的な目的は、ポインターを所有し、いつ、どのように削除するかを決定することだけを目的とする小さなカプセル化されたオブジェクトを提供することです。

もしこのオブジェクトが同じポインタを無意識のうちに巧みに通過させてしまうと、その目的を果たせなくなります。スマート ポインターを掘り下げて内部の生のポインターを取得するときはいつでも、その所有権のセマンティクスに違反しているため、愚かなことをしないように細心の注意を払う必要があります。スマート ポインターを使用すると、誤って間違った種類の関数にポインターを渡すたびに黙って呼び出しを行うのではなく、内部のポインターを取得するための呼び出しを強制することで、これについて考えさせられます。これはスマート ポインターのようなものだと考えてください。

私見、共有ポインターがポインターへのアクセスを許可しない場合、宇宙はより良い場所になります。残念ながら、それはこのユニバースではなく、スマート ポインターを使用しない関数に渡す必要がある場合もあるため、このユニバースになることはできません。だから、私たちはそのより良い宇宙に住んでいないので、私たちのスマートポインターはアクセスを許可します.

于 2010-12-10T17:25:50.690 に答える
1

おそらく方法はありますが、それは一種の汚いものです。階層に別のクラス、ABase を配置してみてください。A は ABase から継承でき、ABase にはすべてのパブリック メソッドのデフォルトの実装が含まれます。このようなもの:

#include <iostream>
#include <boost/shared_ptr.hpp>

class ABase
{
    public:
        ABase() {}
        void init( ABase *a ) { mImpl.reset( a ); }

        virtual void setX( int x ) { mImpl->setX( x ); }
        virtual int getX() const { return mImpl->getX(); }

        boost::shared_ptr< ABase > mImpl;
};

class A : public ABase
{
public:
    typedef ABase BaseClass;

    A(int x) {mX = x;}
    virtual void setX(int x) {mX = x;}
    virtual int getX() const {return mX;}
private:
    int mX;
};


template <class T>
class Shared : public T::BaseClass
{
public:
    Shared(T* t) { init( t ); }
};

int main()
{
    Shared< A > sh( new A( 1 ) );

    std::cout << sh.getX() << std::endl;
    sh.setX( 5 );
    std::cout << sh.getX() << std::endl;
}

これは単なる概念です。コードを確認する必要があります。重要なアイデアは、型 A から直接ではなく、必要なすべての実装を持つ基本型から共有を継承することによって、デフォルトの実装を渡すことです。基本クラスにはもう少し作業が必要ですが、アイデアはかなり明確だと思います。

それはまさにあなたが求めたものではありません(実際には不可能です)が、場合によっては役立つ可能性があり、おそらくあなたが得ることができる最も近いものです.

于 2010-12-10T17:22:56.393 に答える
0

これが良いアイデアかどうかは別として。暗黙的に生のポインターに変換できる共有ポインター型が必要な場合は、pointee 型から継承したり、他のそのような複雑な処理を行ったりする必要はありません。適切な暗黙の変換演算子を使用して共有ポインター型を作成するだけです。

これは、既存の共有ポインター型の継承または構成によって行うことができます。(または、独自の共有ポインターを最初から作成することによって)。

継承の使用例:

template<typename T>
class convertible_shared_ptr : public boost::shared_ptr<T>
{
public:
    convertible_shared_ptr() {}
    convertible_shared_ptr(T* ptr) : boost::shared_ptr<T>(ptr) {}

    operator T* () const
    {
        return get();
    }

    T* operator-> () const
    {
        return get();
    }
};

次に、次のように使用します。

#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;

class A    // simple class for example purposes
{
public:
    A() : member(42) {}

    int member;
};

void foo(A* a)
{
    cout << "a->member=" << a->member << endl;
}

int main()
{
    convertible_shared_ptr<A> ptr(new A);

    foo(ptr);

    cout << "ptr->member=" << ptr->member << endl;

    return 0;
}

もちろん、実際にそのようなことを実際のシナリオで試したことはありません。対応する型と対話しようとすると、いくつかの複雑な問題が発生する可能性がありweak_ptrます。少なくとも、考えられるすべての用途をカバーするには、さらにコードが必要になる可能性があります。

于 2010-12-10T18:14:50.990 に答える