3

ビルダー パターンを使用したいクラスがありますが、そのクラスは、アクセスする必要のある属性を持つ基本クラスから派生しています。BaseClassBuilder を派生させたとしても、BaseClassまたは同様に臭いものから派生させたとしても、公開しないと実装のメンバーにアクセスできません。私のクラス:

BaseClass.h:

class BaseClass
{
    protected:
        CString name;
}

DerivedClass.h:

class DerivedClass : public BaseClass
{
    public:
        // builder starts here and has the same base class as the class it is nested in
        // (if it doesn't, we can't get access to name)
        static class Builder : public BaseClass
        {
            public:

                Builder::Builder(CString pName)
                {
                    this->name = pName;
                }

                Builder Builder::Description(CString pDescription)
                {
                    this->description = pDescription;
                    return *this;
                }
        };

    public:
        CString description;
};

DerivedClass.cpp:

DerivedClass::DerivedClass(Builder builder)
{
    this->name = builder.name; // this is NOT ok
    this->description = builder.description; // this is ok
}

私の問題は、アクセスできないことですbuilder.name。Visual Studio は、「ポインターまたはオブジェクトBaseClass::nameを介して保護されたメンバーにアクセスできない」と言っています。DerivedClass::BuilderのをいじってみましBuilderfriendBaseClass、役に立ちませんでした。この投稿でも回避策が提供されていますが、これは Java 用であり、非常に面倒です。

C++ で継承を使用してビルダー パターンを使用する適切な方法はありますか?

4

2 に答える 2

4

Builderは の内部で宣言されていますが、あなたが期待しているように、 暗黙のうちに と友達ではありませんDerivedClass。は依然として独自のクラスであり、スコープ アクセス規則を含め、他のクラスと同じ規則に従います。そのため、デフォルトでは のメンバーにアクセスできません。その友情を明示的に宣言する必要があります。BuilderDerivedClassBuilderDerivedClassprotectedBuilder

また、メンバーがないBuilder::Description()ため、メソッドはそのままではBuilder機能しませんdescription。メソッド内のthisポインターは、インスタンスではなくインスタンスを参照します。のメンバーにアクセスする場合は、インスタンスへのポインターを指定する必要があります。それ以外の場合は、独自のメンバーを指定します (とにかく実行しようとしていたようです)。BuilderBuilderDerivedClassBuilderDerivedClassDerivedClassBuilderdescription

これを試して:

BaseClass.h:

class BaseClass
{
protected:
    CString name;
};

DerivedClass.h:

class DerivedClass : public BaseClass
{
public:
    class Builder : public BaseClass
    {
    public:
        Builder(const CString &pName)
        {
            this->name = pName;
        }

        Builder& Description(const CString &pDescription)
        {
            this->description = pDescription;
            return *this;
        }

    public:
        CString description; // <-- add this

    friend class DerivedClass; // <-- add this
    };

public:
    DerivedClass(const Builder &builder);

public:
    CString description;
};

DerivedClass.cpp:

DerivedClass::DerivedClass(const DerivedClass::Builder &builder)
{
    this->name = builder.name; // this is ok now
    this->description = builder.description; // this is ok now
}
于 2013-07-09T22:38:11.223 に答える