简体   繁体   中英

Name hiding in c++

#include<iostream>

using namespace std;

class ParentClass {
public: 
     virtual void someFunc(int a){
        printf(" ParentClass :: someFunc (int) \n");
    };

    virtual void someFunc(int* a){
        printf(" ParentClass :: someFunc (int*) \n");
    };
};

class ChildClass : public ParentClass {
public:
    virtual void someFunc(int* a){
        printf(" ChildClass ::  someFunc(int*) \n");
    };
};

int main(){
    ChildClass obj;
    /* This function call results in an error: */
    obj.someFunc(7);
}

The first one gives error as

tr2.cpp: In function 'int main()':
tr2.cpp:27:19: error: invalid conversion from 'int' to 'int*' [-fpermissive]
     obj.someFunc(7);
                   ^
tr2.cpp:18:18: error:   initializing argument 1 of 'virtual void ChildClass::som
eFunc(int*)' [-fpermissive]
     virtual void someFunc(int* a){
                  ^

But if we change the method to accept char instead of int* then

#include<iostream>

using namespace std;

class ParentClass {
public: 
     virtual void someFunc(int a){
        printf(" ParentClass :: someFunc (int) \n");
    };

    virtual void someFunc(char a){
        printf(" ParentClass :: someFunc (char) \n");
    };
};

class ChildClass : public ParentClass {
public:
    virtual void someFunc(char a){
        cout<<a<<endl;
        printf(" ChildClass ::  someFunc(char) \n");
    };
};

int main(){
    ChildClass obj;
    /* This function call results in an error: */
    obj.someFunc(7);
}

output:

 ChildClass ::  someFunc(char)

With a windows sound(ding). - ANS: Implicit Conversion here. Please Check the edit below.

So name hiding works in the first example, but it doesnt in the second example. can anyone explain why? I have also tried making overloaded overridden virtual function with different number of parameters like int func(int a) , int func (int a, int b), and then overriding only one of them. In that case also name hiding isnt working, the derived class is able to derive the virtual function of base class that isnt overridden.

Why is this name hiding only work only in this particular one case?

EDIT 1:

With Context to Eternals Explanation of an implicit conversion. I have another program that should be name hiding but does not. In this version the methods are differentiated on the basis of different no of arguments.

#include<iostream>

using namespace std;

class ABC
{   public:
    ABC()
    {
        cout<<"Constructor ABC"<<endl;
    }
    virtual void meth1(int a);
    virtual void meth2(int a, int b);
};

void ABC :: meth1(int a)
{
    cout<<"One"<<endl;
}   

void ABC:: meth2(int a, int b)
{
    cout<<"Two"<<endl;
}

class BC:public ABC
{
    public:
    BC()
    {
        cout<<"Cons B"<<endl;
    }

    void meth1(int a);
};

void BC :: meth1(int a)
{
        cout<<"Three"<<endl;
}

int main()
{
    BC b;
    b.meth1(5);
    b.meth2(6,7);
}

output:

C:\Users\Shaurya\Desktop>a
Constructor ABC
Cons B
Three
Two

Name hiding does not work in this case either.

When you overload someFunc() in ChildClass , it hides the two overloads from ParentClass . In the first case you are calling a function that takes a int* as argument with an integer, so of course it crashes because it cannot do the conversion.

In the second case, you are calling a function that takes a char as an argument with an integer, so there is an implicit conversion and everything is fine.

Update after EDIT 1:

I don't really get what you were expecting would happen:

  • first you construct a BC , which is a child from ABC , so there is a call to ABC 's constructor then BC 's
  • after that you call meth1() : since BC overrides it, BC::meth1() is called
  • finally you call meth2() : since BC doesn't override it, ABC::meth2() is called

The only "name hiding" that happens here is the override of meth1 by BC,but it's not really hiding anything...

In your "EDIT 1" there's no name hiding. b.meth2(6,7) can't find meth2 in BC , so it looks it up in ABC . But if you rename meth2 to meth1 everywhere in the program, it won't compile because of name hiding: BC::meth1(int) will hide ABC::meth1(int, int) .

EDIT: Brief explanation of how class member lookup works. When the compiler sees object.method(args) , where static type of object is class C , first it looks for the member function member in the declaration of class C . If it finds it (or it's several overloads), it stops looking for the member anywhere else . If not, it looks it up in C 's base classes following some cryptic rules fully described in the C++ standard part 10.2 Member name lookup .

Once candidates are found, the compiler checks if any of the candidates can be called with given arguments. If yes, and this can be done unabmiguously, the function is found. Otherwise the program is ill-formed. This process is called overload resolution and described in part 13.3 of the standard.

Note that there's no word virtual in above explanation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM