C++中的建造者模式与继承

3

我有一个类想要使用生成器模式,但它是从一个基类派生出来的,我需要访问基类的属性。如果我从BaseClass继承Builder或者其他不太好的方式,我就无法在实现中访问BaseClass的成员,即使我将它们设置为public也不行。我的类:

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显示“protected member BaseClass::name is not accessible through a DerivedClass::Builder pointer or object”。我尝试了一些方法,比如将Builder设为BaseClassfriend,但没有成功。这篇文章提供了一个解决方法,但是它是针对Java的,而且很混乱。
有没有一种合理的方式在C++中使用继承与构建器模式?
2个回答

4
尽管Builder声明在DerivedClass内部,但是Builder并不像你期望的那样自动成为DerivedClass的友元。因为Builder仍然是它自己的类,并且遵循与任何其他类相同的规则,包括作用域访问规则。这就是为什么默认情况下DerivedClass无法访问Builder的受保护成员。您需要显式声明友谊关系。
此外,您的Builder :: Description()方法将无法正常工作,因为Builder没有description成员。Builder方法中的this指针仍然指向Builder实例,而不是指向DerivedClass实例。如果您想让Builder访问DerivedClass的成员,它需要被给予一个指向DerivedClass实例的指针。否则,给Builder一个自己的description成员(似乎您本来就是这样做的)。
尝试这个:
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
}

C++11中已更新访问规则。嵌套类现在可以访问封闭类可以访问的所有名称(请参见this)。 - Excambion

3

不要直接访问成员。请使用公共访问器方法。


但是如果成员只是“protected”,我应该能够直接访问它,因为我的“Builder”是从存储成员的“BaseClass”派生的,对吗? - jake
我想知道为什么我在头文件中可以很好地访问成员,但在cpp文件中却不能。 - jake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接