Call Base Class Method from Derived Class Object

Call base class method from derived class object

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.

C++: Calling base class method on derived class member

There are several options with different advantages and disadvantages.

  1. You can make the base class a template like this:
template<class Property>
class Base{
public:
Base(){};
void method(){property.speak();}
Property property;

};

class DerivedA : public Base<A>{
};

class DerivedB : public Base<B>{
};

It is clear and simple, but notice that DerivedA and DerivedB in this case have no common base class, so you can't, e.g. put pointers to them in the same container.


  1. You can use polymorphism.
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;

};

class DerivedA : public Base{
public:
A property;
void method() override { property.speak(); }
};

class DerivedB : public Base{
public:
B property;
void method() override { property.speak(); }
};

This is a bit more complex, involves some code duplication and requires more resources (to store virtual table e.g.), but now the classes really have a common ancestor.


  1. Combine templates and polymorphism
class Base{
public:
virtual ~Base() {}
virtual void method() = 0;

};

template<class Property>
class Derived: public Base {
public:
Property property;
void method() override { property.speak(); }
};

using DerivedA = Derived<A>;
using DerivedB = Derived<B>;

This is actually option #2, but with no code duplication: we make the compiler generate code for us using templates.


  1. Other options. There may be other more specialized options depending on your requirements.

How to call a method of base class with same name method in derived class in python?

Yes, you can call the eat method of Animal directly, passing the object as a parameter.

Animal.eat(mydog)

Though it might make for less confusing code if you give the methods different names instead.

call a base class method using a derived class object outside the derived class

Input:

objb = b()
super(b, objb).fun()

Output:

fun in base class

Edit:

As mentionned in comment below, in Python 2.7+ you need to declare class a(object) for this to work. This comes from a historical evolution of classes in Python, with this solution being functional for "new-style" classes only, i.e. for classes inheriting from object. In Python 3.x however, all classes are "new-style" by default, meaning you don't have to perform this small addition.

Accessing base class's method with derived class's object which has a method of same name

You could add using base::foo to your derived class:

class derived : public base
{
public:
using base::foo;
void foo(int k)
{
std::cout<<"\nHello from foo with value = "<<k<<"\n";
}
};

Edit: The answer for this question explains why your base::foo() isn't directly usable from derived without the using declaration.

C++ how to call method in derived class from base class

You can use a template method:

class Base
{
public:
void Execute()
{
BaseDone(42);
DoDone(42);
}
private:
void BaseDone(int code){};
virtual void DoDone(int) = 0;
};

class Derived : Base
{
public:
void Run() { Execute(); }
private:
void DoDone(int code) { .... }
};

Here, Base controls how its own and derived methods are used in Execute(), and the derived types only have to implement one component of that implementation via a private virtual method DoDone().

Is there a way to forbid a base class method call in the derived class?

This seems like a XY problem. Although I do not recommend this (I recommend rethinking the design) I found (for better or worse) a solution inspired from the CRTP pattern:

template <class D = void>
class Base
{
protected:

int data;

protected:
// This constructor should be called only in the derived classes
template <class Der = D, class = std::enable_if_t<std::is_base_of_v<Base, Der>>>
Base(int d): data(d) {}

public:
// This constructor can be called wherever except a derived classes!
template <class Der = D, class = std::enable_if_t<!std::is_base_of_v<Base, Der>>>
Base(): data(0) { }
};

class Derived : public Base<Derived>
{
int mydata = 1;
public:
// The developer must not forget to initialize "data"
Derived() : Base(24) {}

// I want to get a compilation error there
//Derived() : Base() {} // (1) compilation error here
};
auto test()
{
Base b1{};
//Base b2{24}; // (2) compilation error here

Derived d{};
}

Of course there are problems with this. For starters there is nothing stopping from creating a derived class as class Derived : public Base<void>.

And if you want, you can add a common base class

class Base_l0
{
};

template <class D = void>
class Base_l1 : Base_l0
{
};

class Derived : public Base_l1<Derived>
{
};


Related Topics



Leave a reply



Submit