3

我有一个我想在其上使用构建器模式的类,但它派生自一个我需要访问其属性的基类。我无法BaseClass在不公开的情况下访问我的实现中的成员,即使我从 BuilderBaseClass或同样臭的东西派生。我的课程:

基类.h:

class BaseClass
{
    protected:
        CString name;
}

派生类.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;
};

派生类.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指针或对象访问”。我试过摆弄Buildera friendof BaseClass,但无济于事。这篇文章也提供了一种解决方法,但它是针对 Java 的,而且非常混乱。

有没有一种体面的方法可以在 C++ 中使用具有继承的构建器模式?

4

2 回答 2

4

即使Builder在 内部声明DerivedClass,也不会像您所期望 的那样Builder隐式地与 成为朋友。仍然是它自己的类,它遵循与任何其他类相同的规则,包括范围访问规则。这就是为什么默认情况下无法访问成员的原因。您需要明确声明该友谊。DerivedClassBuilderDerivedClassprotectedBuilder

此外,您的Builder::Description()方法不会按原样工作,因为Builder没有description成员。方法内部的this指针Builder仍然指向Builder实例,而不是DerivedClass实例。如果要Builder访问 的成员DerivedClass,则需要为其提供一个指向DerivedClass实例的指针。否则,给Builder它自己的description成员(看起来你无论如何都试图这样做)。

尝试这个:

基类.h:

class BaseClass
{
protected:
    CString name;
};

派生类.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;
};

派生类.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 回答
3

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

于 2013-07-09T17:52:56.540 回答