【问题标题】:C++ virtual + protected?C ++虚拟+受保护?
【发布时间】:2011-06-01 13:14:26
【问题描述】:

在 C++ 中,我有一个基类 A,一个子类 B。两者都有虚拟方法 Visit。 我想在 B 中重新定义“访问”,但 B 需要访问每个 A(以及所有子类)的“访问”函数。

我有类似的东西,但它告诉我 B 无法访问 A 的受保护成员!但是 B 也是 A :-P

那么,我该怎么办?

class A
{
protected:
virtual Visit(...);
}

class B : public class A
{
protected:
vector<A*> childs;
Visit(...);
}

B::Visit(...)
{
 foreach(A* a in childs)
 {
   a->Visit(...);
 }
}

谢谢

【问题讨论】:

  • 我无法从您的代码中看出 B 是 A 的子类。
  • 你确定你在写 C++ 吗?在 C++ 中,没有 foreach 关键字。
  • foreach(A* a in childs) 是什么?您的代码中是否有一些宏没有告诉我们。
  • @Charles 这是伪代码,就像访问必须返回一些东西,而你不能只是传递...
  • @CashCow:谢谢,下次我会更直接。

标签: c++ class virtual protected


【解决方案1】:

您可以使用自己的对象访问受保护的成员,但不能使用替代对象访问受保护的成员,除非它也是您的类(不仅仅是基类)。

有一种变通方法,就像有一种变通方法不继承友谊一样。

在这个例子的任何情况下:

class A
{
protected:
  virtual void Visit(...);

  void visitOther( A& other, ... )
  {
     other.Visit(...);
  }
};



class B : public A
   {
       Visit(...);
       vector<A*> childs;
   };

   B::Visit(...)
    {
     BOOST_FOREACH( a, childs )
     {
         visitOther( *a, ... );
     }
   }

【讨论】:

  • 是的,我考虑过将其设为静态。
  • 这就是为什么 c++ 是完全蹩脚的头痛。他们甚至搞砸了这个简单的概念。不让以这种方式访问​​受保护的成员有什么意义?为什么它会受到保护?
【解决方案2】:

只要让 B 成为 A 的朋友:

class A  
{  
protected:  
    virtual void Visit();  
    friend class B;  
}; 

class B : public A  
{  
protected:  
    virtual void Visit();  
};

【讨论】:

  • -1 打破了封装,如果我也有一个从 A 派生的 C,但同样的问题怎么办?
  • "friend" 关键字存在,所以当你知道你在做什么时使用它也不错:这里没有提到 C 类,所以你想让场景复杂化什么?
【解决方案3】:

虚函数的本质正是你要逃避的。 这里

foreach (A * in the Childs)
{
  a-> Visit (...);
}

所有a都会调用它对应的访问函数。

没有必要公开从 A 派生,你应该使用 protected。

A中的Visit函数不是虚函数,并做一个受保护的构造函数, 通过继承(以及朋友和 hax)限制实例化。

如果您提供更多详细信息,我们也可以提供更多帮助。

编辑 1:如果您正在玩虚拟,请不要忘记虚拟析构函数。

编辑 2: 试试这个:

foreach (A * in the Childs)
{
  a->A::Visit(...);
}

【讨论】:

    【解决方案4】:

    听听编译器告诉你你的设计被搞砸了,不要再假装你知道得更好。公开访问。更好的是,让它成为非虚拟的:

    struct A { 
      void Visit() { impl_visit(); }
    private:
      virtual void impl_visit();
    };
    
    struct B : A {
    private:
      Vector<A*> childs;
      void impl_visit() {
        ... 
        foreach child in childs child->Visit();
        ...
      }
    };
    

    哦,当你在请求委员会添加漂亮的“foreach/in”语法时。 [我是认真的,他们正在寻找使 C++ 更易于使用的方法!]

    【讨论】:

      【解决方案5】:

      在“示例”中已更正。现在 B 是 A 的子类。

      【讨论】:

        猜你喜欢
        • 2023-03-23
        • 2014-04-08
        • 2011-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        相关资源
        最近更新 更多