Home > Software engineering >  function in derived but not in base class, pointer to base --> "not a member" error
function in derived but not in base class, pointer to base --> "not a member" error

Time:12-18

As the title states, I have a base class (interface) and several derived classes. On the derived classes, I have some extra functions that don't make sense to implement on the interface class - neither on all derived classes.

In my program, I have a vector of pointers to base classes - but the actual objects are all of derived classes.

Now, if I try to call a function of a derived class, I get a compiler error. Even if I know for sure the derived type that a particular object will have, I cannot call the function.

How do I get around this? Would this point to a design problem? Should I convert the pointer/create a new pointer of that specific type?

The last option seems to work, but makes the code very ugly with tons of if-else blocks.

Here is some example code to reproduce the error:

#include <iostream>

class Base {
public:
    Base() {};
    ~Base() = default;
};
    
class Derived: public Base {
public:
    Derived() {};
    ~Derived() = default;
    void foo() {
        std::cout << "foo()" << std::endl;
    }
};
    
int main()
{
    Base* ptr = new Derived();
    *ptr->foo();
    delete ptr;
}

CodePudding user response:

To run the function of derived class from the base class pointer, make sure that the function you want to run have same name and return type function in base class and in addition make sure that the function in base class has virtual keyword before to its return type. Let me explain with an example....

#include<iostream>
using namespace std;

class base{
public:
virtual void func(){
    cout<<"hello";
 }
};

 class derived: public base
{
 public:
 void func(){
     cout<<"Hi";
 }
 };

  int main(){
  base* b1=new derived;
  b1->func();
  return 0;
  }

here the base class pointer is pointing to function of derived class...

Understand that thing the function you want to run should have same name and return type in both of the classes but in addition there is the virtual key word before this function in the base class.

CodePudding user response:

Yes there is a way around it, by something what is called "down casting" but you do not want to go there, as you already mentioned in your question - would it be a design problem? Yes, it would.

Instead you need to understand the basic differences between compile time polymorphism and runtime polymorphism. You in your given sample are trying to achieve runtime polymorphism.

Try to think of it this way:

When you are creating an interface (base class), you are creating something that demonstrates what functionalities are available. In a train it would be the main controls that allow you to operate the train.

The implementation (derived class) of that interface is hidden from you (you don't see how the red button starts up the engine).

In programming it is the same. In your interface (base class) you need to define what will be available to you, but you don't have to implement it. To do this you need the virtual keyword to define a (pure) virtual function, which you define later. I won't go into detail how virtual functions work (you can read about that yourself). I.e.:

#include <iostream>
class Base {
public:
    Base() {};
    ~Base() = default;
    //foo() is virtual and can have it's own implementation
    //you can still override this function in the derived class
    virtual void foo() {std::cout << "foo";}; // virtual function
    //pure virtual functions are without an implementation and must be
    //implemented in their derived classes
    virtual void bar() = 0; //pure virtual 
};

Now in your sample what you are doing (without virtual functions) is the following:

int main()
{
  //You are creating a pointer to Base class, your compiler knows
  //this during compile time. During runtime you are allocating
  //a Derived class and pointing to it with the Base ptr
  Base* ptr = new Derived(); 
  //During compile time it doesn't know that you are supposed to
  //be able to call this function, because it still sees it as a 
  //Base class. If this would pass the compilation it would have 
  //a problem during runtime as well! It wouldn't be able to find
  //the function, because you didn't tell the program that Base 
  //class is supposed to in the case of polymorphism
  //expect such a function (it did not create a hidden pointer in
  //it's vtable that could potentially store the function pointer)  
  *ptr->foo();
  delete ptr;
}

I recommend reading about:

  1. Virtual method table
  2. Polymorphism

Hope it helps!

  • Related