Jos*_*vin 23 c++ standards inheritance constructor c++11
在C++ 0x中,您可以使用using关键字继承构造函数,如下所示:
class B { B(int) {} };
class A : public B { using B::B; };
Run Code Online (Sandbox Code Playgroud)
这将隐式声明一个A(int)构造函数.这适用于模板吗?
class B { B(int) {} };
template<class T> class A : public T { using T::T; };
Run Code Online (Sandbox Code Playgroud)
在内部T::T,我希望编译器找出左手,T因为在模板参数上使用范围运算符是正常的,但是确定右手T是构造函数是一种特殊情况.事实上,它似乎有歧义:如果我有一个名为方法T中B,我试图以重载在增加A(这是一个编译器会如何解释这种使用预申报的C++ 0x)?
Joh*_*itb 10
是的它有效,原因是名称查找机制.继承构造函数声明的工作机制很简单:如果using声明的名称引用基类构造函数,那就是继承构造函数声明.在3.4.3.1 [class.qual] p2,我们发现:
在查找中,构造函数是可接受的查找结果,而嵌套名称说明符指定类C
- 如果在嵌套名称指定者之后指定的名称(在C中查找时)是C的注入类名(第9条),或者
- 如果在嵌套名称说明符之后指定的名称与标识符中的名称或者在嵌套名称说明符
而是将该名称视为命名C类的构造函数.
这是使类构造函数定义工作的段落,这也是使继承构造函数声明起作用的段落.在这种情况下,第二个子弹适用:
struct B {
B(int) { }
};
typedef B mytype;
struct A : B {
// "name ... is the same as the identifier ... in the last component ..."
using mytype::mytype;
};
template<typename T> using same = T;
struct C : B {
// "name ... is the same as the template-name ... in the last component ..."
same<B>::same;
};
Run Code Online (Sandbox Code Playgroud)
后一个例子证明在以下情况下也是有用的
template<template<typename> class Base>
struct X : Base<int> {
using Base<int>::Base;
};
Run Code Online (Sandbox Code Playgroud)
综上所述:
上面的第一个子弹是一个语义规则 - 如果嵌套名称说明符后面的名称引用注入的类名(B::B或mytype::B),那么它将被转换为引用构造函数.
第二个项目符号是一个语法规则 - 名称必须匹配 - 否则它们的含义无关紧要 - 可能Base在提供的模板参数中调用了一个成员X,如下所示,但using声明仍然会导入构造函数和不要不名称的成员Base:
template<typename T> struct D { private: T Base; };
X<D> x; // valid, the private member is *not* touched!
Run Code Online (Sandbox Code Playgroud)是的,根据标准(2011年2月草案)第12.9节,它似乎是这样的:
template< class T >
struct D : T {
using T::T; // declares all constructors from class T
~D() { std::clog << "Destroying wrapper" << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)
类模板D包装任何类并转发其所有构造函数,同时每当D类对象被销毁时将消息写入标准日志. - 例子
另外需要注意的是,虽然标准允许,但根据此列表,只有1个编译器IBM XLC++在发行版中支持此功能.GCC目前仅通过补丁支持它.
编辑:AJG85指出模板中的T总是引用占位符,因此'using T :: T'总是引用模板参数.