thumala manish
thumala manish

Reputation: 318

What is the point in using a "using" declaration in this context?

Let's say I have two classes as below. Is there any advantage or disadvantage of using a using declaration in the derived class, to specify that we will be using the base class version of the method?

More importantly, is the altered derived class the same as the original derived class?

// BASE CLASS                        
template <typename T>               
class base {                        
public:                             
    base (T val): value(val){}      
                                    
    void val(int i) {               
        value += i;                 
    }                               

private:                            
    T value;                        
};                                  
                                    
// DERIVED CLASS                                    
template <typename T>                               
class derived: public base<T> {                     
public:                                             
    derived (T val): value2(val), base<T>(val){}    

    void val(int k) {                               
        base<T>::val(k);                            
        value2 += k;                                
    }                                               

private:                                            
    T value2;                                       
};                                                  

// ALTERED DERIVED CLASS                                    
template <typename T>
class derived: public base<T> {
public:
    derived (T val): value2(val), base<T>(val){}
                                                    
    using base<T>::val;                             

    void val(int k) {
        base<T>::val(k);
        value2 += k;
    }

private:
    T value2;
};

Upvotes: 1

Views: 116

Answers (1)

Chris Uzdavinis
Chris Uzdavinis

Reputation: 6131

In this particular case, if nothing else changes, you won't observe any differences, but it's not exactly the same in general.

The using in the derived will pull all the corresponding symbols from the base class into derived's scope. The difference is pretty clear here:

#include <iostream>

struct Base {
    void foo(int) { std::cout << "Base::foo(int)\n"; }
};
struct Derived : Base {
    // using Base::foo;
    void foo(long) { std::cout << "Derived::foo(long)\n"; }
};

int main() {
    Derived d;
    d.foo(123);
}

https://godbolt.org/z/TdEYsbesv

Output is:

Derived::foo(long)

but if you uncomment the using in Derived, then the output changes to:

Base::foo(int)

The reason is that the name lookup stops once a scope matches the name it's seeking. Without the using, once a name found in the derived class, it will not look in the base class for more overloads--even if there's a better match there.

The using makes the base class symbols appear alongside the derived names, so that the combination of base+derived overload set is searched when a name is looked up on a derived class. (If a function with the same signature is provided in both base and derived, the derived version will still be picked if you invoke the call on a derived object.)

Upvotes: 1

Related Questions