在CRTP pattern中,如果我们想让派生类中的实现函数保持受保护状态,我们就会遇到问题。我们必须将基类声明为派生类的朋友,或者使用something like this (我还没有在链接的文章上尝试过该方法)。有没有其他(简单的)方法可以让派生类中的实现函数保持受保护?
编辑:下面是一个简单的代码示例:
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
,但如果protected
被public
替换,则会进行编译。
发布于 2011-12-16 02:08:00
这根本不是问题,只需在派生类中使用一行代码即可解决:
friend class Base< Derived >;
#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 );
}
发布于 2019-05-01 05:20:39
正如lapk推荐的,问题可以通过简单的友类声明来解决:
class D: public C<D> {
friend class C<D>; // friend class declaration
protected:
void foo() {
}
};
但是,这会公开派生类的所有受保护/私有成员,并且需要为每个派生类声明编写自定义代码。
以下解决方案基于linked article
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%的反汇编代码行):
int base_bar() { return Accessor::base_bar(_instance_ref); }
private:
#define _instance_ref *static_cast<D*>(this) //D& derived() { return *(D*)this; }
https://stackoverflow.com/questions/8523762
复制相似问题