变量的访问修饰符:Private vs Protected

时间:2010-11-23 12:31:01

标签: c++ templates access-modifiers

我有一个案例,我找不到合适的解决方案。我需要有模板基类和一个对该基类做一些工作的管理器类。这是代码

class Base;

class Manager
{
public:
    void DoSomethingTo(Base * bclass)
    {
        if(bclass->PrivateVar == 0)
            // Some code
    }
}

class Base
{
protected: 
    int PrivateVar;
friend class Manager;
};

template<class T>
class TempBase : public Base
{
private:
    Manager * man;
public:
    void DoWork()
    {
        PrivateVar = 0;
        man->DoSomethingTo(this);
    }
}

我的问题是PrivateVar变量实际上必须是TempBase的私有,并且不能从TempBase派生的类访问,但由于我无法将其指针传递给Manager::DoSomethingTo(),我必须从Base类和Base类派生它必须拥有PrivateVar。因为我在TempBase中使用PrivateVar,所以它不能是Base的私有,这使得它可以从TempBase的子类访问。

如何编写TempBase类,以便PrivateVar是私有成员,而可以从Manager::DoSomethingTo()访问它?

由于

5 个答案:

答案 0 :(得分:2)

首先,让我们开始火焰战:

  

类的属性永远不会是protected的原因。它应该是private(在大多数情况下)或者可能是某些角落public。请注意,因为每个派生类都会看到protected属性,protected只会带来一种错误的安全感:一个人无法控制protected属性的任何不变量,所以它基本上是{{1}一个,带有注释不要触摸

既然已经说完了,我建议只需将其更改为:

public

通过将测试的责任委托给变量的所有者,我们会轻轻地绕过所有的担忧。当然,如果我们需要多个类以类似的方式运行,那么我们可以在class Base {}; template <typename T> class TBase; class DoKey { template <typename T> friend class TBase; DoKey(); }; class Manager { public: void DoSomethingTo(Base& base, DoKey const& key); }; template <typename T> class TBase: public Base { public: void Do() { Manager manager; if (PrivateVar == 0) { manager.DoSomething(*this, DoKey()); } } private: int PrivateVar; }; 中引入纯虚void ShouldIDoSomething() const并在Base的方法中检查它。

答案 1 :(得分:1)

删除Base内的访问保护,然后私下继承。

class Manager
{
public:
    void DoSomethingTo(struct Base * bclass);
};

struct Base
{
    int PrivateVar;
};

void Manager::DoSomethingTo(struct Base * bclass)
{
    if(bclass->PrivateVar == 0)
        ; // Some code
}

template<class T>
class TempBase : private Base
{
private:
    Manager * man;
public:
    void DoWork()
    {
        PrivateVar = 0;
        man->DoSomethingTo(this);
    }
};

答案 2 :(得分:0)

您可以将受保护的成员函数放入Base本身:

class Base
{
protected:
   void sendPrivateVarToManager( Manager& manager )
   {
      manager.DoSomethingToPrivateVar( privateVar );
   }
};

由于Base不是模板,实现实际上可以放在Base之外。

您的另一个问题是您希望privateVar存在于Base中,对TempBase是可见的,而不是层次结构中的任何其他内容。您可以将其移动到TempBase中,在这种情况下,您也可以将sendPrivateVarToManager放在该类中,尽管您必须实现它,或者将privateVar作为参数传递给它。你的另一个选择是让TempBase成为Base的朋友,但这似乎是错误的。我不确定为什么TempBase需要访问。

答案 3 :(得分:0)

您可以将PrivateVar设为私有,并将TempBaseManager朋友设为Base。见here。请注意,此代码不是最干净的代码。

答案 4 :(得分:0)

我认为我可以将一个公共的纯虚函数放到Base来检索PrivateVar,同时将PrivateVar保存在TempBase中。

class Manager
{
public:
    void DoSomethingTo(Base * bclass)
    {
        if(bclass->GetPrivateVar() == 0)
            // Some code
    }
}
class Base
{
private:
virtual int GetPrivateVar() = 0;  
friend class Manager;
};

template<class T>
class TempBase : public Base
{
private:
    Manager * man;
    int PrivateVar;
    int GetPrivateVar() {return PrivateVar;}
public:
    void DoWork()
    {
        PrivateVar = 0;
        // Some code
        man->DoSomethingTo(this);
        // Some code
    }
friend class Manager;
}