我有一个类我想使用构建器模式,但它是从我需要访问其属性的基类派生的。即使我从BaseClass
或同样臭的东西派生出构建器,我也无法在我的实现中访问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
指针或对象访问#34;。我试图摆弄Builder
friend
BaseClass
,但无济于事。这个post也提供了一种解决方法,但它适用于Java,而且非常混乱。
在C ++中使用带继承的构建器模式是否有合适的方法?
答案 0 :(得分:3)
即使在Builder
内宣布了DerivedClass
,Builder
也不会与DerivedClass
隐含的朋友一样,就像您期望的那样。 Builder
仍然是它自己的类,它遵循与任何其他类相同的规则,包括范围访问规则。这就是DerivedClass
默认无法访问protected
Builder
成员的原因。你需要明确宣布这种友谊。
此外,由于Builder::Description()
没有Builder
成员,因此description
方法无法按原样运作。 this
方法内的Builder
指针仍然引用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
}
答案 1 :(得分:2)
请勿尝试直接访问该成员。使用公共访问方法。