In a derived class If I redefine/overload a function name from a Base class,
then those overloaded functions are not accessable/visible to derived class.
Why is this??
If we don't overload the oveloaded function from the base class in derived class
then all the overloaded versions of that function are available to derived class
objects, why is this??
what is the reason behind this. If you explain this in compiler and linker level
that will be more helpful to me. is it not possible to support this kind of scinario??
Edited
For examble:
class B
{
public:
int f() {}
int f(string s) {}
};
class D : public B
{
public:
int f(int) {}
};
int main()
{
D d;
d.f(1);
//d.f(string); //hidden for D
}
Now object 'd' can't access f() and f(string).
TTBOMK this doesn't have a real technical reason, it's just that Stroustrup, when creating the language, considered this to be the better default. (In this it's similar to the rule that rvalues do not implicitly bind to non-const references.)
You can easily work around it be explicitly bringing base class versions into the derived class' scope:
class base {
public:
void f(int);
void g(int);
};
class derived : public base {
public:
using base::f;
void f(float);
void g(float); // hides base::g
};
or by calling the explicitly:
derived d;
d.base::g(42); // explicitly call base class version
The functions are available, you just need to call them explicitly:
struct A {
void f(){}
};
struct B : public A {
void f() {}
};
int main() {
B b;
b.f(); // call derived function
b.A::f(); // call base function
}
Related
In a derived class If I redefine/overload a function name from a Base class,
then those overloaded functions are not accessable/visible to derived class.
Why is this??
If we don't overload the oveloaded function from the base class in derived class
then all the overloaded versions of that function are available to derived class
objects, why is this??
what is the reason behind this. If you explain this in compiler and linker level
that will be more helpful to me. is it not possible to support this kind of scinario??
Edited
For examble:
class B
{
public:
int f() {}
int f(string s) {}
};
class D : public B
{
public:
int f(int) {}
};
int main()
{
D d;
d.f(1);
//d.f(string); //hidden for D
}
Now object 'd' can't access f() and f(string).
TTBOMK this doesn't have a real technical reason, it's just that Stroustrup, when creating the language, considered this to be the better default. (In this it's similar to the rule that rvalues do not implicitly bind to non-const references.)
You can easily work around it be explicitly bringing base class versions into the derived class' scope:
class base {
public:
void f(int);
void g(int);
};
class derived : public base {
public:
using base::f;
void f(float);
void g(float); // hides base::g
};
or by calling the explicitly:
derived d;
d.base::g(42); // explicitly call base class version
The functions are available, you just need to call them explicitly:
struct A {
void f(){}
};
struct B : public A {
void f() {}
};
int main() {
B b;
b.f(); // call derived function
b.A::f(); // call base function
}
The code below won't compile:
struct Base
{
std::vector<void(Base::*)(void)> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
Is it possible to refer derived class in template member x? In the example above I specify exactly Base and derived classes cannot push their own member functions into vector x.
Casting is bad since your code have to assume that this will be called only for instance of Derived class. This means that you either have to assume that all items in x are instance of Derived (in such case declaration of x is to general and should be changed to std::vector<void(Derived::*)(void)> x;) or you have to maintain extra information what which class method is stored in specific position of x. Both approaches are bad.
In modern C++ it is much better do do it like this:
struct Base
{
std::vector<std::function<void()>> x;
};
struct Derived : public Base
{
void foo() {}
};
// ...
Derived d;
d.x.push_back([&d](){ d.foo(); });
Another good approach can be CRTP:
template<class T>
struct Base
{
std::vector<void(T::*)(void)> x;
};
struct Derived : public Base<Derived>
{
void foo() {}
};
// ...
Derived d;
d.x.push_back(&Derived::foo);
You may, but there is no implicit conversion; it requires a cast.
Derived d;
d.x.push_back(static_cast<void(Base::*)()>(&Derived::foo));
The caveat is the if you use that pointer to member with an object that isn't really a Derived, the behavior is undefined. Tread carefully.
As an addendum, if you want to get rid of the cast when taking the pointer, you can do that by encapsulating the push (with some static type checking to boot):
struct Base
{
std::vector<void(Base::*)(void)> x;
template<class D>
auto push_member(void (D::* p)()) ->
std::enable_if_t<std::is_base_of<Base, D>::value> {
x.push_back(static_cast<void(Base::*)()>(p));
}
};
I think I would express this by calling through a non-virtual member function on the base.
example:
#include <vector>
struct Base
{
std::vector<void(Base::*)(void)> x;
// public non-virtual interface
void perform_foo()
{
foo();
}
private:
// private virtual interface for the implementation
virtual void foo() = 0;
};
struct Derived : public Base
{
private:
// override private virtual interface
void foo() override {}
};
// ...
int main()
{
Derived d;
d.x.push_back(&Base::perform_foo);
auto call_them = [](Base& b)
{
for (auto&& item : b.x)
{
(b.*item)();
}
};
call_them(d);
}
Let's consider the following code:
#include <iostream>
class Base
{
public:
void foo() //Here we have some method called foo.
{
std::cout << "Base::foo()\n";
}
};
class Derived : public Base
{
public:
void foo() //Here we override the Base::foo() with Derived::foo()
{
std::cout << "Derived::foo()\n";
}
};
int main()
{
Base *base1 = new Base;
Derived *der1 = new Derived;
base1->foo(); //Prints "Base::foo()"
der1->foo(); //Prints "Derived::foo()"
}
If I have the above stated classes, I can call the foo method from any of Base or Derived classes instances, depending on what ::foo() I need. But there is some kind of problem: what if I need the Derived class instance, but I do need to call the Base::foo() method from this instance?
The solve of this problem may be next:
I paste the next method to the class Derived
public:
void fooBase()
{
Base::foo();
}
and call Derived::fooBase() when I need Base::foo() method from Derived class instance.
The question is can I do this using using directive with something like this:
using Base::foo=fooBase; //I know this would not compile.
?
der1->Base::foo(); //Prints "Base::foo()"
You can call base class method using scope resolution to specify the function version and resolve the ambiguity which is useful when you don't want to use the default resolution.
Similar (Not exactly same case) example is mentioned # cppreference
struct B { virtual void foo(); };
struct D : B { void foo() override; };
int main()
{
D x;
B& b = x;
b.foo(); // calls D::foo (virtual dispatch)
b.B::foo(); // calls B::foo (static dispatch)
}
I tried using CRTP with this (simplified) example:
Base class:
template <class Derived>
class Base
{
public:
int method(int in, int& out2)
{
return derived().method(in, out2);
}
int method(int in)
{
int dummy;
return this->predict(in, dummy);
}
protected:
Base() {}
private:
Derived& derived()
{
return *static_cast<Derived*>(this);
}
};
Derived class:
class Derived : public Base<Derived>
{
public:
int method(int in, int& out2)
{
// Logic here
}
};
The problem is, when I try to use method(int in) with an instance of the Derived class, like:
Derived d;
int res = d.method(5);
The compiler (icc in this case, but have also tried with msvc) gives me the following error:
error #165: too few arguments in function call
It seems that the compiler is not realizing that there exists an overload which only takes one parameter, from the Base<Derived> class (from which Derived inherits publicly, so I think it should be accesible).
I'm not sure what I'm missing here, any hints will be deeply appreciated.
The presence of Derived::method means that the compiler will not consider overloads of Base::method when attempting to bind the call. To fix this, add using Base::method; to the derived class:
class Derived : public Base<Derived>
{
public:
using Base::method;
int method(int in, int& out2)
{
// Logic here
}
};
When a non-virtual function is defined with the same name as a Base::method, it overshadows the Base::method in the Derived class, which is also known as Name Hiding.
To prevent this, you have to explicitly mention the name of the method with the class using the using operator, i.e. your Derived class code should be modified to:
class Derived : public Base<Derived>
{
public:
using Base::method; //makes the 'method' declaration of Base class
//visible here as well.
int method(int in, int& out2)
{
// Logic here
}
};
How can I call a base class method which is overridden by the derived class, from a derived class object?
class Base{
public:
void foo(){cout<<"base";}
};
class Derived:public Base{
public:
void foo(){cout<<"derived";}
}
int main(){
Derived bar;
//call Base::foo() from bar here?
return 0;
}
You can always(*) refer to a base class's function by using a qualified-id:
#include <iostream>
class Base{
public:
void foo(){std::cout<<"base";}
};
class Derived : public Base
{
public:
void foo(){std::cout<<"derived";}
};
int main()
{
Derived bar;
//call Base::foo() from bar here?
bar.Base::foo(); // using a qualified-id
return 0;
}
[Also fixed some typos of the OP.]
(*) Access restrictions still apply, and base classes can be ambiguous.
If Base::foo is not virtual, then Derived::foo does not override Base::foo. Rather, Derived::foo hides Base::foo. The difference can be seen in the following example:
struct Base {
void foo() { std::cout << "Base::foo\n"; }
virtual void bar() { std::cout << "Base::bar\n"; }
};
struct Derived : Base {
void foo() { std::cout << "Derived::foo\n"; }
virtual void bar() { std::cout << "Derived::bar\n"; }
};
int main() {
Derived d;
Base* b = &d;
b->foo(); // calls Base::foo
b->bar(); // calls Derived::bar
}
(Derived::bar is implicitly virtual even if you don't use the virtual keyword, as long as it's signature is compatible to Base::bar.)
A qualified-id is either of the form X :: Y or just :: Y. The part before the :: specifies where we want to look up the identifier Y. In the first form, we look up X, then we look up Y from within X's context. In the second form, we look up Y in the global namespace.
An unqualified-id does not contain a ::, and therefore does not (itself) specify a context where to look up the name.
In an expression b->foo, both b and foo are unqualified-ids. b is looked up in the current context (which in the example above is the main function). We find the local variable Base* b. Because b->foo has the form of a class member access, we look up foo from the context of the type of b (or rather *b). So we look up foo from the context of Base. We will find the member function void foo() declared inside Base, which I'll refer to as Base::foo.
For foo, we're done now, and call Base::foo.
For b->bar, we first find Base::bar, but it is declared virtual. Because it is virtual, we perform a virtual dispatch. This will call the final function overrider in the class hierarchy of the type of the object b points to. Because b points to an object of type Derived, the final overrider is Derived::bar.
When looking up the name foo from Derived's context, we will find Derived::foo. This is why Derived::foo is said to hide Base::foo. Expressions such as d.foo() or, inside a member function of Derived, using simply foo() or this->foo(), will look up from the context of Derived.
When using a qualified-id, we explicitly state the context of where to look up a name. The expression Base::foo states that we want to look up the name foo from the context of Base (it can find functions that Base inherited, for example). Additionally, it disables virtual dispatch.
Therefore, d.Base::foo() will find Base::foo and call it; d.Base::bar() will find Base::bar and call it.
Fun fact: Pure virtual functions can have an implementation. They cannot be called via virtual dispatch, because they need to be overridden. However, you can still call their implementation (if they have one) by using a qualified-id.
#include <iostream>
struct Base {
virtual void foo() = 0;
};
void Base::foo() { std::cout << "look ma, I'm pure virtual!\n"; }
struct Derived : Base {
virtual void foo() { std::cout << "Derived::foo\n"; }
};
int main() {
Derived d;
d.foo(); // calls Derived::foo
d.Base::foo(); // calls Base::foo
}
Note that access-specifiers both of class members and base classes have an influence on whether or not you can use a qualified-id to call a base class's function on an object of a derived type.
For example:
#include <iostream>
struct Base {
public:
void public_fun() { std::cout << "Base::public_fun\n"; }
private:
void private_fun() { std::cout << "Base::private_fun\n"; }
};
struct Public_derived : public Base {
public:
void public_fun() { std::cout << "Public_derived::public_fun\n"; }
void private_fun() { std::cout << "Public_derived::private_fun\n"; }
};
struct Private_derived : private Base {
public:
void public_fun() { std::cout << "Private_derived::public_fun\n"; }
void private_fun() { std::cout << "Private_derived::private_fun\n"; }
};
int main() {
Public_derived p;
p.public_fun(); // allowed, calls Public_derived::public_fun
p.private_fun(); // allowed, calls Public_derived::public_fun
p.Base::public_fun(); // allowed, calls Base::public_fun
p.Base::private_fun(); // NOT allowed, tries to name Base::public_fun
Private_derived r;
r.Base::public_fun(); // NOT allowed, tries to call Base::public_fun
r.Base::private_fun(); // NOT allowed, tries to name Base::private_fun
}
Accessibility is orthogonal to name lookup. So name hiding does not have an influence on it (you can leave out public_fun and private_fun in the derived classes and get the same behaviour and errors for the qualified-id calls).
The error in p.Base::private_fun() is different from the error in r.Base::public_fun() by the way: The first one already fails to refer to the name Base::private_fun (because it's a private name). The second one fails to convert r from Private_derived& to Base& for the this-pointer (essentially). This is why the second one works from within Private_derived or a friend of Private_derived.
First of all Derived should inherit from Base.
class Derived : public Base{
That said
First of you can just not have foo in Derived
class Base{
public:
void foo(){cout<<"base";}
};
class Derived : public Base{
}
int main(){
Derived bar;
bar.foo() // calls Base::foo()
return 0;
}
Second you can make Derived::foo call Base::foo.
class Base{
public:
void foo(){cout<<"base";}
};
class Derived : public Base{
public:
void foo(){ Base::foo(); }
^^^^^^^^^^
}
int main(){
Derived bar;
bar.foo() // calls Base::foo()
return 0;
}
Third you can use qualified id of Base::foo
int main(){
Derived bar;
bar.Base::foo(); // calls Base::foo()
return 0;
}
Consider making foo() virtual in the first place.
class Base {
public:
virtual ~Base() = default;
virtual void foo() { … }
};
class Derived : public Base {
public:
virtual void foo() override { … }
};
However, this does the job:
int main() {
Derived bar;
bar.Base::foo();
return 0;
}
An important [additional] note: you will still have compilation errors if Name Hiding occurs.
In this case, either utilize the using keyword, or use the qualifer. Additionally, see this answer as well.
#include <iostream>
class Base{
public:
void foo(bool bOne, bool bTwo){std::cout<<"base"<<bOne<<bTwo;}
};
class Derived : public Base
{
public:
void foo(bool bOne){std::cout<<"derived"<<bOne;}
};
int main()
{
Derived bar;
//bar.foo(true,true); // error: derived func attempted
bar.foo(true); // no error: derived func
bar.Base::foo(true,true); // no error: base func, qualified
return 0;
}