基类中的常见受保护数据成员?

时间:2010-06-10 21:37:35

标签: c++

我有一个基类和几个派生类。派生类使用一些常见数据,我可以将这些常用数据作为基类的受保护成员吗?我知道受保护的成员有时会破坏封装,所以我想知道是否有任何好的方法。

这是一个具体的例子:

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中具有相同的功能,这对我来说没有多大意义。

有没有更好的方法来处理这个而不使用受保护的成员?谢谢。

5 个答案:

答案 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类中是有意义的。

我认为没有把它放在那里的原因是:

  1. 如果您的界面(抽象基类)被冻结,那么您将被迫使用该存储或中断用户兼容性。
  2. 避免强迫用户#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;
};