基类变量的“ using”关键字

问题描述

| 我正在浏览WildMagic 5引擎(www.geometrictools.com),其中Vector <>类继承自Tuple <>类,该类具有一个特定大小的数组,名为
mTuple[]
(由模板参数设置)。到目前为止还不错,没什么特别的。但是,在Vector类中,我看到以下内容
protected:
    using Tuple<4,Real>::mTuple; 
现在,我知道
using
关键字用于正确继承重载方法在这种情况下,我始终假设变量可用于派生类而无需键入上面的代码。以上必要吗?还是只是为了使事情更清楚?     

解决方法

        通用编程与面向对象编程略有不同。 您的“ 3”是一个非依赖性名称的示例。就编译器而言,在处理模板定义时,编译器不知道类模板继承了名为“ 3”的数据成员。这对您来说可能很明显,但对编译器来说却并不明显。在这一阶段,编译器已不为所知。 如果派生类模板的方法希望使用父类模板的某些成员,则需要明确告知编译器这样做。因此,
using
。 编辑 以上有点简洁。重要的是要记住,这些类模板不是类。它们是最终定义类的模板。直到使用类模板定义类的那一刻,该类模板还不是很真实。更重要的是,对于从其他类模板继承的类模板,这种继承不是很真实。除非明确告知继承,否则编译器不知道该继承。这就是为什么您将看到派生类模板通过“ 6”导入父类成员的原因(例如)。 编辑#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!
#1
将导致错误,因为在模板中,不合格的查找不会查找相关的基类。这是C ++中的重要概念。如果有一个全局
a
可见,那么
a = 0
将使用
a
-在从属基类中声明的成员将永远不会隐藏该全局
a
。为了告诉编译器研究依赖的基类,必须限定名称。所以
this->a
B::a
一样有效。 如果放置
using A<T>::a
,则告诉编译器在
B
范围内声明成员名
a
。然后
a = 0
将直接在
B
中找到
a
。这也是可以接受的解决方案。     ,        通常,您可以使用这样的声明来增加对继承成员的访问。从
protected
public
说。 但是您不能使用此语法来限制访问。您不能在声明为“ 23”的成员上使用它。 因此,这唯一可以做的就是Vector是从Tuple <>继承的,就像这样:
class Vector4 : private Tuple<4,Real>
{ ... }
在这种情况下,此“ 2”声明将使“ 3”受到保护而不是私有。 我相信,在所有其他情况下,它什么也不会做。 [编辑] 对于模板基类,我的想法是错误的。请参阅约翰尼斯和戴维的答案。