变量的访问修饰符:私有与受保护

发布于 2024-10-04 16:31:43 字数 815 浏览 5 评论 0原文

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

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(),所以我有要从基类派生它,基类必须拥有 PrivateVar。由于我在 TempBase 中使用 PrivateVar,它不能是 Base 的私有变量,这使得它可以从 TempBase 的子类访问。

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

谢谢

I have a case that I could not find a proper solution. I need to have template base class and a manager class that does some work to that base class. Here is the code

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);
    }
}

My problem is PrivateVar variable actually must be private to TempBase and not be accesible from classes derived from TempBase, but since I can not pass its pointer to Manager::DoSomethingTo(), I have to derive it from Base class and Base class must own the PrivateVar. And since I use PrivateVar in TempBase it can not be private to Base, which makes it accessible from the child classes of TempBase.

How can I write the TempBase class so that PrivateVar is a private member whereas it can be reached from Manager::DoSomethingTo() ?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

骄傲 2024-10-11 16:31:43

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

类的属性永远不会被保护。它应该是私有(在大多数情况下),或者在某些极端情况下可能是公共。请注意,因为每个派生类都会看到一个 protected 属性,所以 protected 只会带来一种错误的安全感:人们无法控制 protected 上的任何不变量。属性,因此它本质上是一个 public 属性,其顶部有一条注释 Don't Touch

现在这一切都已经说了,我建议将其简单地更改为:

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;
};

通过将测试的责任委托给变量的所有者,我们可以温和地解决所有的担忧。当然,如果我们需要多个类以类似的方式表现,那么我们可以在 Base 中引入一个纯虚 void ShouldIDoSomething() const 并在 中检查它经理的方法。

First of all, let's start the flame war:

There is never a reason for an attribute of a class to be protected. It shall either be private (in most cases) or perhaps in some corner cases public. Note that because every derived classes would see a protected attribute, protected only brings a false sense of security: one cannot control any invariant on a protected attribute, so it's essentially a public one, with a comment Don't Touch on top of it.

Now that this is said and done, I would propose to simply change this to:

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;
};

By delegating the responsibility of the test to the owner of the variable, we gently circle around all our worries. Of course if we need multiple classes to behave in a similar fashion, then we could introduce a pure virtual void ShouldIDoSomething() const in Base and check it in the Manager's method.

廻憶裏菂餘溫 2024-10-11 16:31:43

删除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);
    }
};

Remove access protection inside Base, then inherit privately.

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);
    }
};
情绪 2024-10-11 16:31:43

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

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

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

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

You could put a protected member function into Base itself:

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

As Base is not a template the implementation could actually be put outside of Base.

Your other issue is you want privateVar to exist in Base, be visible to TempBase but not anything further down the hierarchy. Either you could move it into TempBase in which case you can also put sendPrivateVarToManager in that class although then you'd have to implement it, or pass privateVar as a parameter to that too. Your other option would be to make TempBase a friend of Base but that seems wrong. I am not sure why TempBase needs access.

硬不硬你别怂 2024-10-11 16:31:43

您可以将 PrivateVar 设为私有,并将 TempBaseManager 设为 Base 的好友。请参阅此处。请注意,这段代码并不是最干净的。

You can make PrivateVar private, and make both TempBase and Manager friends of Base. See here. Note that this code is not the cleanest one.

乄_柒ぐ汐 2024-10-11 16:31:43

我认为我可以将一个公共纯虚函数放入 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;
}

I thought that I could put a public pure virtual function to Base to retrieve PrivateVar, while keeping PrivateVar in 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文