C ++中的多个声明

时间:2015-07-30 01:09:54

标签: c++ c++11 language-lawyer

在[basic.scope.declarative] p4中,一个读取

  

在单个声明区域中给出一组声明,每个声明指定相同的非限定名称, - (4.1)它们都应引用同一个实体......

天真的阅读可能意味着以下代码可能有效,因为“两个声明都引用同一个实体”:

int x;
int x;

然后可能会记住一个定义规则[basic.def.odr] p1。上述推理可能仅适用于不是定义的声明。区别在[basic.def] p2中详细说明。例如,以下代码肯定有效:

extern int x;
extern int x;

[basic.def] p2中的最后一个示例表明以下代码应该有效,但不能编译(使用MSVC2015)。

struct B
{
    int y;
};

struct D : B
{
    using B::y;
    using B::y;
};

问题出在哪里?

错误消息是

  

'B :: y'的using声明不能与'B :: y'的现有using声明共存

2 个答案:

答案 0 :(得分:5)

[namespace.udecl] p10中的这个例子与你的完全相同:

struct B {
   int i;
};
struct X : B {
   using B::i;
   using B::i; // error: double member declaration
};

错误由[class.mem] p1:

备份
  

成员不得在 member-specification 中声明两次,   除了可以声明嵌套类或成员类模板   然后定义,除了枚举可以   引入了 opaque-enum-declaration ,后来又重新声明了   枚举说明符

所以你正走在正确的轨道上。多个声明都可以,只要它们不违反其他规则(例如一个定义,成员规范等)。

例如,以下内容很好:

struct X;
struct X;

或更复杂的例子:

struct X 
{
    struct A;
    struct A
    {
       int y;
    };
}; 

struct X;
struct X::A;

答案 1 :(得分:0)

你几乎通过引用namespace.udecl / 10回答了你自己的问题。下面的示例(N3936)显示了允许多个等效using声明的位置:

namespace A {
    int i;
}
namespace A1 {
    using A::i;
    using A::i; // OK: double declaration
}
void f() {
    using A::i;
    using A::i; // error: double declaration
}
struct B {
    int i;
};
struct X : B {
    using B::i;
    using B::i; // error: double member declaration
};

多个using - 在命名空间块范围内也允许函数声明。至于为什么在块范围内不允许它们用于变量(对象),我不知道。可能不允许多个等效成员声明,​​原因有两个:

  • 初始化订单错误的巨大潜力
  • 历史上没有必要,因为内联定义的方法主体"见"稍后在同一个类中声明的成员(在C ++ 11中引入decltype,这个原因不再是明确的)