CRTP中能否访问父类体内成员?C++11/14/17父类如何访问子类成员?
CRTP相关成员访问问题解答
1. 使用CRTP时,能否访问父类体内的成员?
当然可以!CRTP本质也是继承关系,子类继承模板父类后,和普通继承规则完全一致——能直接访问父类的public或protected成员。比如父类里有个protected方法foo(),子类里直接调用foo()就行,不需要额外特殊处理。
2. 在C++11/14/17中,使用CRTP时是否有办法在父类中访问子类的成员?
必须可以,但要把握模板实例化的时机:当父类模板A<T>被实例化时(比如子类B继承A<B>),子类T已经完成了声明(虽然定义可能还没完全结束),所以子类的成员声明是可见的,父类可以基于这些声明做类型推导或成员引用。
针对你给出的代码示例分析
你的代码意图是让A<B>::C和B::C都指向B::next()的返回类型int,这个思路完全可行,还能根据不同C++版本优化写法:
C++11/14版本
#include <type_traits> template <typename T> class A { public: // 利用std::result_of推导成员函数的返回类型 using C = typename std::result_of<decltype(&T::next)(T)>::type; }; class B : public A<B> { public: int next() { return 42; }; };
C++17及以后版本(更推荐)
C++17里std::result_of被标记为废弃,建议用更直观的std::invoke_result替代:
#include <type_traits> template <typename T> class A { public: using C = typename std::invoke_result<decltype(&T::next), T>::type; }; class B : public A<B> { public: int next() { return 42; }; }; // 验证类型是否符合预期 static_assert(std::is_same_v<typename A<B>::C, int>); static_assert(std::is_same_v<typename B::C, int>);
关键注意点
- 父类只能访问子类的
public成员(除非子类把父类声明为友元),如果next()是private或protected,父类就无法获取&T::next的地址。 - 这种方式依赖子类成员的声明可见性:对于成员函数,只要子类里声明了函数签名(哪怕定义在类外),父类就能推导类型;但如果是成员变量,需要确保父类使用时变量已经被定义(不过CRTP场景下更多是用成员函数做类型推导)。
内容的提问来源于stack exchange,提问作者Niklas R
相关产品推荐
相关产品推荐

