c++language-lawyerderived-classredefinitionusing-declaration

Why is this compiling successfully?


What is the reason which why this code compile :

#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" 

I mean ( I am expecting having error (redefinition function in human class )) like this : this code compile :

#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;
}

but when i add ( using 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;
}

the error appear: error C2086: 'int being::v': redefinition

why this error did not appear in the first code ?


Solution

  • This is expected behavior of using declaration.

    If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.

    So human::running(char) hides being::running(char) instead of conflict.

    EDIT

    The 2nd code snippet is ill-formed. For data members, from the standard, [namespace.udecl]/10:

    If a declaration named by a using-declaration that inhabits the target scope of another declaration potentially conflicts with it ([basic.scope.scope]), and either is reachable from the other, the program is ill-formed. If two declarations named by using-declarations that inhabit the same scope potentially conflict, either is reachable from the other, and they do not both declare functions or function templates, the program is ill-formed.

    [Example 6:

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

    So you can't using being::v which conflicts with human::v. But for member functions, [namespace.udecl]/11:

    The set of declarations named by a using-declarator that inhabits a class C does not include member functions and member function templates of a base class that correspond to (and thus would conflict with) a declaration of a function or function template in C.

    [Example 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)
    };
    ...