我有一个基类和几个派生类。派生类使用一些常见数据,我可以将这些常用数据作为基类的受保护成员吗?我知道受保护的成员有时会破坏封装,所以我想知道是否有任何好的方法。
这是一个具体的例子:
class Base{
public:
virtual void foo() = 0;
void printData();
protected:
std::vector<std::string> mData;
}
class Dr1 : public Base{
public:
virtual void foo(); //could change mData
}
class Dr2 : public Base{
public:
virtual void foo(); //could change mData
}
如果我将mData作为私有成员放入Dr1和Dr2中,那么我需要将它放在两个中,并且我不能在Base中使用printData()因为printData()需要访问mData,除非我创建printData()虚拟并且在Dr1和Dr2中具有相同的功能,这对我来说没有多大意义。
有没有更好的方法来处理这个而不使用受保护的成员?谢谢。
答案 0 :(得分:8)
这是有争议的。允许数据protected
被添加到C ++中,主要是因为Mark Linton想要它用于他正在设计的Interviews Windowing库。它似乎与C ++的其他设计相当合适,所以(显然)Bjarne赞同这个想法。几年后,Mark禁止在Interviews中使用受保护的数据成员,因为使用它们会导致错误的数量。在此之后的一段时间,Barbara Liskov就整个概念提出了理论和实际问题的讨论。
在 C ++的设计和演变中,Bjarne得出结论:“回想起来,我认为protected
是一个案例,我让”好的论据“和时尚克服了我更好的判断力我接受新功能的经验法则。“
结论:我对制作您的数据protected
有第二和第三个想法。现在看来这可能是一个好主意,但维护可能是一个完全不同的故事。
答案 1 :(得分:3)
要考虑的一个设计是将mData设为私有,并向Base添加受保护的方法,以便为数据提供常见的操作,然后Dr1和Dr2可以使用这些方法。
但是有很多时候将mData作为受保护的成员更有意义。最好的方法很大程度上取决于你班级的细节。
答案 2 :(得分:1)
我得出结论,受保护的数据与类中的公共数据一样糟糕。如果您需要更改受保护的数据,您将打破从基础派生的所有类。这些派生类是基类的客户端,就像常规的“公共”用户一样。我建议编写派生类可以调用的受保护的访问器函数。这为您提供了公共成员函数的所有好处:您可以在不破坏客户端的情况下更改实现,并且可以根据需要轻松添加检测和错误检查。
答案 3 :(得分:0)
只要所有派生类都有成员是有意义的,就把它放在Base类中是有意义的。
我认为没有把它放在那里的原因是:
#include <string>
和<vector>
。答案 4 :(得分:0)
我认为,如果您没有将此类公开为其他子类的库,那么给予子类访问您的数据是可以的。但是,如果您确实想要或需要隐藏子类中数据的实际实现,则可以将mData
设为私有并为其创建受保护的访问者:
class Base {
protected:
// figure out what interface you want for your subclasses:
// do they need the whole enchilada? or can you give them
// a few more targeted kinds of modification routines?
// one example:
void add_data(const std::string& d) { mData.push_back(d); }
private:
std::vector<std::string> mData;
};