【问题标题】:Why is this compiling successfully?为什么编译成功?
【发布时间】:2021-10-29 09:06:03
【问题描述】:

这段代码编译的原因是什么:

#include <iostream>
using namespace std;
class being {
public:
  void running(char c) {
        cout << "No one know ";
    }
};
class human :public being {
public:
    using being::running;
    void running(char y) {
        cout << "I am a human";
    }
};

int main() {
    human o;
    o.running('A');
    return 0;
}


the output : "I am a human" 

我的意思是(我期待有错误(人类类中的重新定义函数)) 像这样 : 这段代码编译:

#include <iostream>
using namespace std;
class being {
public:
    int v;
};
struct human :public being {
public:
    
    double v;

};

int main() {
    human o;
    o.v = 55.2;
    return 0;
}

但是当我添加(使用being::v)

#include <iostream>
using namespace std;
class being {
public:
    int v;
};
struct human :public being {
public:
    using being::v;

    double v;

};

int main() {
    human o;
    o.v = 55.2;
    return 0;
}

出现错误:error C2086: 'int being::v': redefinition

为什么第一个代码中没有出现这个错误?

【问题讨论】:

  • 你为什么期待这个? (它不是;“使用”这个词没有正常的英语含义。)

标签: c++ language-lawyer derived-class redefinition using-declaration


【解决方案1】:

这是using declaration 的预期行为。

如果派生类已经有一个具有相同名称、参数列表和限定条件的成员,则派生类成员隐藏或覆盖(不冲突)从基类引入的成员。

所以human::running(char) 隐藏 being::running(char) 而不是冲突。

编辑

第二个代码 sn-p 格式错误。对于数据成员,来自标准,[namespace.udecl]/10

如果位于另一个声明的目标范围内的 using-declaration 命名的声明可能与它([basic.scope.scope])发生冲突,并且其中一个可以从另一个访问,则该程序格式错误。如果位于同一范围内的两个使用声明命名的声明可能发生冲突,其中一个可以从另一个访问,并且它们既没有声明函数也没有声明函数模板,则程序是非良构的。

[示例 6:

...

namespace B {
  int i;
  ...
}

void func() {
  int i;
  using B::i;                           // error: conflicts
  ...
...

所以你不能using being::vhuman::v 冲突。但是对于成员函数,[namespace.udecl]/11

由位于类 C 中的 using-declarator 命名的声明集不包括与C.

[示例 7:

struct B {
  virtual void f(int);
  virtual void f(char);
  void g(int);
  void h(int);
};

struct D : B {
  using B::f;
  void f(int);      // OK: D​::​f(int) overrides B​::​f(int);

  using B::g;
  void g(char);     // OK

  using B::h;
  void h(int);      // OK: D​::​h(int) hides B​::​h(int)
};
...

【讨论】:

  • 仅供参考,OP 已更新问题,澄清了他们为何预计会出现重新定义错误。
  • "human::running 隐藏being::running" 不完全是。 human::running(char) 隐藏 being::running(char) 但如果 being::running 有任何其他签名,它们将作为 human::running(char) 的重载可见(这是 using 所做的更改,没有 using 声明,那么 human::running(char) 确实会隐藏being::running的所有签名)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 2016-10-14
  • 2021-07-07
  • 1970-01-01
相关资源
最近更新 更多