【问题标题】:Accessing protected member of template parameter访问模板参数的受保护成员
【发布时间】:2011-03-22 20:08:10
【问题描述】:

我有一个模板类,我需要访问模板参数的受保护成员函数,如下所示:

class Foo
{
protected:
    void foo() {}
};

template<typename T>
class Bar
{
public:
    static void bar(T& self){self.foo();}
};
...
Foo f;
Bar<Foo>::bar(f);

我的问题是访问受保护的方法。我尝试将friend class T 放入Bar,但这似乎在c++ 中是不允许的(编辑:无论如何也不能解决我的问题,所以看起来)。我尝试让 Bar 从 T 继承(template&lt;typename T&gt; class Bar: public T(可以使用私有继承,但 Bar 的公共接口并不是非常重要,因为类本身只是内部的)),但这不允许访问 @987654324 @ 任何一个。那么如何访问foo() 方法呢?

编辑: Foo 不需要知道 Bar&lt;Foo&gt;,因为有很多 Bar 类。但是,我可以对 Foo 进行其他更改(当然不更改公共接口)。

【问题讨论】:

  • 这是作业吗?您应该查找受保护的含义。这将告诉您谁有权访问该方法。
  • 不,这不是家庭作业,这不是关于谁可以访问该方法,而是如何让没有该方法的类可以访问它。以及如何查找受保护的帮助我解决这个问题(除了我通常知道这意味着,我只是没有遇到过这样的情况,所以向它抛出继承似乎是一个很好的起点)?

标签: c++ templates visibility


【解决方案1】:

好的,这是一个“地狱腐烂”的黑客攻击。您可以滥用这样一个事实,即您可以形成指向派生类中受保护基成员的成员指针。

class Foo
{
protected:
    void foo() {}
};

// Helper template to bypass protected access control
// for a member function called foo, taking no parameters
// and returning void.
template<typename T>
struct Unprotect : public T
{
    typedef void (T::*FooPtr)();
    static FooPtr GetFooPtr()
    {
        return &Unprotect::foo;
    }
};

template<typename T>
class Bar
{
public:
    static void bar(T& self){(self.*Unprotect<Foo>::GetFooPtr())();}
};

int main()
{
    Foo f;
    Bar<Foo>::bar(f);
}

【讨论】:

  • 这可能是骇人听闻的,它应该可以完成这项工作,而且由于这些类不供外部使用,我可以忍受一些丑陋的代码,所以谢谢。
  • 这很有趣。还有一些方法可以绕过私人访问:bloglitb.blogspot.com/2010/07/… :)
  • @litb:很好,我也认为不可能颠覆私人保护。
【解决方案2】:

你在错误的方向做了你的朋友声明。如果BarFoo 是它的朋友,这意味着Foo 可以访问Bar 的私人数据。对于Bar 要访问Foo 的私人数据,Foo 必须说Bar 是它的朋友。

【讨论】:

  • 我认为它的工作方式正好相反,但我通常避免使用朋友,所以无论如何。正如我在编辑中指定的那样,将 Bar 作为 Foo 的朋友并不是一个真正的选择,所以虽然很高兴知道,但这并不能真正解决我的问题(应该早点指定,我知道)
  • 要么是这个,要么什么都不是。阅读我提供的答案。
【解决方案3】:
template<typename T>
class Bar
{
public:
    static void bar(T& self){self.foo();}
};

class Foo
{
protected:
    void foo() {}
    friend class Bar<Foo>;
};

void main()
{
    Foo f;
    Bar<Foo>::bar(f);
}

【讨论】:

  • 虽然可行,但它并不是我真正想要的解决方案,因为我有几个“Foo”和几个“Bar”类(它们可以相互组合),所以放入每个组合选项的朋友类并不是一个好的解决方案。
【解决方案4】:

如果你想访问一个this的派生类的受保护成员,你可以使用using关键字:

class A
{
protected:
  void i_am_protected () {}
};

template <class T>
class B : public T
{
  using T::i_am_protected;

  void call_me ()
  {
    i_am_protected(); // OK.
    this->i_am_protected(); // This compiles without the keyword.
  }
};

如果在将对象传递给 B 时需要 B 访问 A 的受保护成员,则需要将 B 声明为 A 的友元:

class A
{
  template <class T>
  friend
  class B;

protected:
  void i_am_protected () {}
};

template <class T>
class B : public T
{
  void call_me (T& obj)
  {
    obj.i_am_protected(); // OK.
  }
};

【讨论】:

    猜你喜欢
    • 2018-11-06
    • 2019-09-28
    • 1970-01-01
    • 2013-09-17
    • 2017-08-01
    • 2016-10-01
    • 2013-08-06
    • 2015-01-30
    相关资源
    最近更新 更多