首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >具有受保护派生成员的CRTP

具有受保护派生成员的CRTP
EN

Stack Overflow用户
提问于 2011-12-16 00:57:49
回答 2查看 5.4K关注 0票数 33

CRTP pattern中,如果我们想让派生类中的实现函数保持受保护状态,我们就会遇到问题。我们必须将基类声明为派生类的朋友,或者使用something like this (我还没有在链接的文章上尝试过该方法)。有没有其他(简单的)方法可以让派生类中的实现函数保持受保护?

编辑:下面是一个简单的代码示例:

代码语言:javascript
复制
template<class D> 
class C {
public:
    void base_foo()
    {
        static_cast<D*>(this)->foo();
    }
};


class D:  public C<D> {
protected: //ERROR!
    void foo() {
    }   
};

int main() {
    D d;
    d.base_foo();
    return 0;
}

上面的代码给出了带有g++ 4.5.1的error: ‘void D::foo()’ is protected,但如果protectedpublic替换,则会进行编译。

EN

回答 2

Stack Overflow用户

发布于 2011-12-16 02:08:00

这根本不是问题,只需在派生类中使用一行代码即可解决:

friend class Base< Derived >;

代码语言:javascript
复制
#include <iostream>

template< typename PDerived >
class TBase
{
 public:
  void Foo( void )
  {
   static_cast< PDerived* > ( this )->Bar();
  }
};

class TDerived : public TBase< TDerived >
{
  friend class TBase< TDerived > ;
 protected:
  void Bar( void )
  {
   std::cout << "in Bar" << std::endl;
  }
};

int main( void )
{
 TDerived lD;

 lD.Foo();

 return ( 0 );
}
票数 35
EN

Stack Overflow用户

发布于 2019-05-01 05:20:39

正如lapk推荐的,问题可以通过简单的友类声明来解决:

代码语言:javascript
复制
class D:  public C<D> {
    friend class C<D>;      // friend class declaration
protected:
    void foo() {
    }
};

但是,这会公开派生类的所有受保护/私有成员,并且需要为每个派生类声明编写自定义代码。

以下解决方案基于linked article

代码语言:javascript
复制
template<class D>
class C {
public:
    void base_foo() { Accessor::base_foo(derived()); }
    int base_bar()  { return Accessor::base_bar(derived()); }

private:
    D& derived() { return *(D*)this; }

    // accessor functions for protected functions in derived class
    struct Accessor : D
    {
        static void base_foo(D& derived) {
            void (D::*fn)() = &Accessor::foo;
            (derived.*fn)();
        }
        static int base_bar(D& derived) {
            int (D::*fn)() = &Accessor::bar;
            return (derived.*fn)();
        }
    };
};

class D : public C<D> {
protected: // Success!
    void foo() {}
    int bar() { return 42; }
};

int main(int argc, char *argv[])
{
    D d;
    d.base_foo();
    int n = d.base_bar();
    return 0;
}

PS:如果你不相信你的编译器会优化掉引用,你可以用下面的#define替换derived()函数(使用MSVC2013减少了20%的反汇编代码行):

代码语言:javascript
复制
    int base_bar() { return Accessor::base_bar(_instance_ref); }

    private:
    #define _instance_ref *static_cast<D*>(this)   //D& derived() { return *(D*)this; }
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8523762

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档