Sam*_*rsa 13 c++ inheritance using-statement
我正在浏览WildMagic 5引擎(www.geometrictools.com),其中Vector <>类继承自Tuple <>类,该类具有特定大小的数组,名为mTuple[](由模板参数设置).到目前为止这么好,没什么特别的.但是在Vector类中,我看到以下内容:
protected:
using Tuple<4,Real>::mTuple;
Run Code Online (Sandbox Code Playgroud)
现在我知道该using关键字用于正确继承重载方法.在这种情况下,我总是假设变量可用于派生类而无需键入上面的代码.以上是必要的吗?或者只是为了让事情更清楚?
通用编程与面向对象编程略有不同.
您mTuple是一个非独立名称的示例.就编译器而言,在处理模板定义时,编译器不知道类模板是否继承了名为的数据成员mTuple.这对您来说可能是显而易见的,但对编译器来说并不明显.在这个阶段,编译器忽视了显而易见的事实.
如果派生类模板的方法希望使用父类模板的某些成员,则需要明确告知编译器这样做.因此using.
编辑
以上有点简洁.重要的是要记住,那些类模板不是类.它们是最终定义类的模板.直到类模板用于定义类模板不太真实的类的时刻.更重要的是,对于从其他类模板继承的类模板,该继承不是很真实.除非明确告知它,否则编译器不知道该继承.这就是为什么你会看到派生类模板通过using ParentClass<Type>::member(例如)导入父类的成员.
编辑#2
Marshall Cline在他的C++中讨论了这个主题 - 常见问题解答,网址为http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19
编辑#3
(根据请求)仅仅因为编译器上的某些代码编译并不意味着它在每个编译器上编译(对于相同的语言).编译器供应商将自己的"功能"添加到一种语言中,有时非常有意,有时只是因为供应商自己搞砸了,有时候因为标准本身就是错误的.这个不太标准的编译器问题长期以来一直是许多语言的问题.在泛型编程方面,这个问题显然非常猖獗.
你可以做任何事情(或者你认为):打开所有标准警告然后一些,通过一些商业代码分析器运行你的代码,你仍然可能没有可移植的代码.
@David一直在说什么,但有些人显然没有理解.所以我相信一个例子是有序的:
template<typename T>
struct A { int a; };
template<typename T>
struct B : A<T> {
void f() {
a = 0; // #1
this->a = 0; // #2
B::a = 0; // #3
}
// using A<T>::a;
};
template<>
struct A<float> { }; // surprise!
Run Code Online (Sandbox Code Playgroud)
#1将导致错误,因为在模板中,非限定查找不会查找依赖的基类.这是C++中的一个重要概念.如果全局a可见,那么a将使用a = 0- 在依赖基类中声明的成员永远不会隐藏该全局a.为了告诉编译器查看依赖的基类,您必须限定您的名称.因此this->a工作得很好B::a.
如果你输入using A<T>::a,你告诉编译器a在范围内声明一个成员名称B.然后a = 0会a直接找到B.这也是一个可接受的解决方案.