Reputation: 318
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
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