问题描述
尝试理解CRTP几天后,现在我的理解似乎比以前更少了:)
After trying to understand CRTP for several days it seems that now I understand even less than before:)
考虑以下代码:
01 #include <iostream>
02
03 template <class IMPL>
04 class Interace
05 {
06 public:
07 typedef typename IMPL::TYPE TYPE; // ERROR: "...invalid use of incomplete type..."
08 void foo() { IMPL::impl(); } // then why does this work?
09 };
10
11 class Implementation : public Interface<Implementation>
12 {
13 public:
14 typedef int TYPE;
15 static void impl() { std::cout << "impl() " << std::endl; }
16 };
17
18
19 int main()
20 {
21 Implementation obj;
22 obj.foo();
23 }
问题是:
-
为什么我可以从
IMPL::
调用函数(第8行),但是不能访问类型文件(第7行)?在相关问题中,据说IMPL
在这一点上是不完整的类型.但是为什么第8行正确呢?
Why I can call function from
IMPL::
(line 8) but cannot access type fileds (line 7)? In related question it is said thatIMPL
is an incomplete type at this point. But why then line 8 is correct?
类型声明/定义的顺序是什么?如我所见:
What it the order of type declaration/definition? As I see it:
a. Interface
模板-确定.在实例化之前不会带来任何问题
a. Interface
template -- OK. Doesn't bring any problems until instantiating
b.第11行-在class Implementation
-Implementation
类型已声明但未定义的位置之后.
b. line 11 -- after class Implementation
-- Implementation
type declared but not defined.
c.第11行-在Interface<Implementation>
之后-模板实例化.此时,由于步骤(b),Implementation
是已知的(但未定义!).编译器用IMPL
替换为Implementation
的注入"代码.在我看来,第7行和第8行都不是不合法的,因为在这一点上,编译器不知道Implementation
具有这些成员.怎么知道呢?
c. line 11 -- after Interface<Implementation>
-- template instantiation. At this point Implementation
is already known (but not defined!) due to step (b). Compiler "injects" code with IMPL
replaced with Implementation
. Here, to my point of view, neither line 7, neither line 8 are not legal because at this point, compiler doesn't know that Implementation
has these members. How does it knows than?
也许实例化确实在第21行?但是在那种情况下,为什么07行不起作用?
Or maybe Instantiation really goes at line 21? But in that case why line 07 doesn't work?
我想的更多,对我拥有的C ++类型基础知识的了解也较少.任何澄清表示赞赏.
More I think about it, less understanding of C++ type fundamentals I have. Any clarification is appreciated.
推荐答案
实例化类模板时,将实例化除非虚拟成员函数以外的成员.但是,非虚拟成员函数仅在使用时会实例化(基本上是调用或使用其地址).
When a class template is instantiated, its members other than non-virtual member functions are instantiated together with it. Non-virtual member functions, however, are only instantiated when odr-used (basically, called or have their address taken).
当编译器遇到class Implementation : public Interface<Implementation>
时,它需要实例化Interface<Implementation>
.此时,Implementation
仍然是不完整的类型,尚未看到其TYPE
成员.另一方面,Interface<Implementation>::foo
仅在稍后在main
中被调用时实例化.此时,Implementation
是完整类型.
When the compiler encounters class Implementation : public Interface<Implementation>
, it needs to instantiate Interface<Implementation>
. At this point, Implementation
is still an incomplete type, its TYPE
member has not yet been seen. On the other hand, Interface<Implementation>::foo
is only instantiated later, when it's called in main
. At that point, Implementation
is a complete type.
这篇关于CRTP-访问不完整的类型成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!