2010-11-23 113 views
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()达成?

感谢

回答

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

你可以把一个受保护的成员函数到基地本身:

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

为基是不是一个模板的实施实际上可以基地外放。

你的另一个问题是你想privateVar在基地进一步存在,是可见的TempBase但没有什么下降的层次结构。要么你可以将它移动到TempBase在这种情况下,你也可以把sendPrivateVarToManager在该类虽然那么你就必须实现它,或者通过privateVar作为参数传递到这一点。你的其他选择是让TempBase成为Base的朋友,但看起来不对。我不确定为什么TempBase需要访问。

+0

从设计,我不知道为什么`基地`需要访问。显然`PrivateVar`纯粹是一个`TempBase`的东西,它转移到`Base`,以便`Manager`可以访问它。在阅读代码时,我曾有过解开一盘意大利面的印象:/ – 2010-11-23 13:09:32

+0

@Matthieu M .:对于为什么`Base`需要访问,你绝对正确。对于混乱的代码感到抱歉。 – 2010-11-23 13:19:23

2

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

从未有一类的属性是protected的理由。它应该是private(在大多数情况下)或者可能是在某些角落案例public。请注意,由于每个派生类都会看到protected属性,因此protected只会带来错误的安全感:无法控制protected属性上的任何不变量,因此它本质上是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; 
}; 

通过委派测试的责任,该变量的拥有者,我们轻轻地圈住所有的后顾之忧。当然,如果我们需要多个类以类似的方式行事,那么我们就可以在Base推出纯虚拟void ShouldIDoSomething() const并检查它在Manager的方法。

0

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

0

我认为我可以把公共纯虚函数库检索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; 
}