0

I have base class called Base and a derived class of Base called Derived, A Base Class pointer can point to a derived class object and can also access its resource but I am getting an error doing the same.

class Base
{
public:
    int a;
};

class Derived : public Base
{
public:
    float b;
    void DoSomething()
    {
         cout<<"Derived";
    }
};

int main()
{
    Base * pBase = new Derived();
    pBase->DoSomething();
    pBase->a = 5; 
    pBase->b = 0.2f; 
    return 0;
}

This gives me an error

main.cpp: In function ‘int main()’:
main.cpp:34:25: error: ‘class Base’ has no member named ‘DoSomething’
     pBase->DoSomething();
                         ^
main.cpp:36:12: error: ‘class Base’ has no member named ‘b’
     pBase->b = 0.2f;
            ^

Pardon me if its too basics, I am a beginner in c++

  • 2
    If you are using a `Derived` as a `Base`, it is limited by what `Base` knows. `Base` has no `DoSomething` so `Base` cannot use `DoSomething`. – user4581301 Jun 04 '20 at 17:37
  • But see this `Base * pBase = new Derived();` we can do this. I have studied that this is allowed i.e A base class pointer can store reference to its derived class –  Jun 04 '20 at 17:39
  • `Derived` [is-a](https://en.wikipedia.org/wiki/Is-a) `Base`. It knows everything `Base` knows, and can be used as a `Base`. But `Base` cannot know what `Derived` knows. That `Base*` could be pointing to a `Derived` and it could be pointing at an `AlsoDerived`, which has different functionality. [Look into `virtual` methods](https://en.cppreference.com/w/cpp/language/virtual) if you want behaviour in `Base` that may be specified by classes derived from `Base`. – user4581301 Jun 04 '20 at 17:45

1 Answers1

1

Yes you can use a Base pointer to a Derived class, nonetheless, the Base pointer must know the methods in order to choose what's the most suited for the call, if the Base pointer has no knowledge of the existence of these variables and functions it cannot call them.

Corrected code:

class Base
{
public:
    int a;
    float b;
    virtual ~Base(){} //virtual destructor required
    virtual void DoSomething() //implementing DoSomething in base class
    {
        std::cout << "Base";
    }
};

class Derived : public Base
{
public:
    void DoSomething() override //override DoSomething() in base class
    {
         std::cout<<"Derived";
    }
};
Base * pBase = new Derived();
//Base will choose the most suited DoSomething(), depending where it's pointing to
pBase->DoSomething(); 
pBase->a = 5;
pBase->b = 0.2f; 

Output:

Derived

Edit:

As you suggested in the comment section, casting the derived class will work in this specific case, but it usually reveals poorly designed code, as pointed out by @user4581301's comment, also note the link provided that has some of the reasons why this is not the best idea.

As I said, if you must do it, use dynamic_cast<>() instead.

Note that, in any case, you still need the virtual destructor for a correct implementaion of polymorphism.

Virtual destructors

Deleting an object through pointer to base invokes undefined behavior unless the destructor in the base class is virtual.

and that's not all, check this link.

Community
  • 1
  • 1
anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • After little bit of research I found that I was looking for static cast `static_cast(pBase)->DoSomething();` if you could edit your answer explaining the same I could accept answer to this question. Also could you mention is there any cons of doing this way –  Jun 04 '20 at 17:57
  • 1
    @FarhanAhmed You should avoid casting from base to derived. Sometimes you must, but much, much more often you have a flaw in the design. If you have to do this a lot, the classes should not have an inheritance relationship at all. – user4581301 Jun 04 '20 at 18:00
  • @FarhanAhmed, though this works in this specific case it's not at all recommended to do it, this most certainly lead to very poorly designed code, but if you must do it, `dynamic_cast` is better. – anastaciu Jun 04 '20 at 18:03
  • Consider this: In order to use a cast in this manner you must know with absolute certainty the `Base*` points to a `Derived`, and if you know this with absolute certainty, why are you using `Base` at all? – user4581301 Jun 04 '20 at 18:07
  • @FarhanAhmed, I added some further info to my answer, be sure to check it out. – anastaciu Jun 04 '20 at 19:44