-3

I have 2 classes:

#include <iostream>
using namespace std;

class A
{
public:
    virtual void print()=0;
};

class B: public A
{
public:
    void print()
    {
        cout<<"B\n";
    }

    void printNew()
    {
        cout<<"Print new";
    }
};

int main()
{
    B b;
    A *a=new B;
    a->printNew();
    delete a;
}

The compiler posts an error. If I want to use printNew through A, how can I do it? I thought it must include this feature because this proves useful in various situations.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
W.Joe
  • 335
  • 2
  • 8
  • 1
    declare `a` as `B*` ? – orhtej2 Sep 10 '18 at 14:32
  • 6
    `A` doesn't have a method named `printNew`, hence why you get a compiler error. Why do you think, that it should have worked? – Algirdas Preidžius Sep 10 '18 at 14:33
  • Possible duplicate of [When should static\_cast, dynamic\_cast, const\_cast and reinterpret\_cast be used?](https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used) – zett42 Sep 10 '18 at 14:35
  • When you're using pointer to base class, you're only allowed to use methods declared in base class (even if object was created as object of derived class). – Rhathin Sep 10 '18 at 14:35
  • Bonus point: if your class B definition includes `void print() override{...}` you can save many headaches later on. – Tim Randall Sep 10 '18 at 14:39
  • @Downvoters: Might I point out that this question is clearly presented (although stating the actual error would make it even better). I don't see what is so bad here. Roll forward to C++20 when we can answer such questions with reflective code. – Bathsheba Sep 10 '18 at 14:41
  • "this proves useful in various situations." if you think about it more you will find out that it isnt that useful. Actually there are only two situations, either A) you know for sure that the `A*` really points to a `B*`, then you can simply cast, or ask yourself, why you used a `A*` in the first place. B) you dont know for sure that the `A*` is really pointing to a `B*`, in that case it would be no good, actually harmful, if you were allowed to call a method of `B` on an instance of `A` – 463035818_is_not_an_ai Sep 10 '18 at 14:59
  • @user463035818: I think it could be, although I don't think it would be possible to implement in C++ as it supports multiple inheritance. In Java, for example, you could postulate the syntax `a?.printNew()` where `printNew` is called if the dynamic instance of `a` has that method. Note that in Java, all objects are polymorphic. It would open your code up to maintenance headaches though which is why, deep down, I think such things are best left to reflection. – Bathsheba Sep 10 '18 at 15:05
  • @Bathsheba yeah well, only after writing my wordy comment I realized that it just boils down to either you can cast you you cannot ;). Actually I am not sure if OP really has the premise that it is known that `a` does point to a `B` or if that is just my understanding, your interpretation seems to be a bit more general – 463035818_is_not_an_ai Sep 10 '18 at 15:10

2 Answers2

6

Having a subclass instance B in a superclass A pointer is called Polymorphism in OOP. From this A-type pointer, you would not be able to see the member function which exists only in B-type, clearly. You could use this object as a B-type object by downcasting it though:

B *B = dynamic_cast<B*>(a);

As a has a dynamic type of B*, the cast is safe so a B pointer is returned.

Zzyzx
  • 501
  • 3
  • 7
  • The key point about a static_cast is that you must verify that the pointer returned from the cast is valid, which will happen unless `a` isn't a pointer to `B`. (Again, if you are 100% certain that it is, there is no reason for a dynamic cast and you should review why you're using the wrong type of pointer in the first place.) – Tim Randall Sep 10 '18 at 15:22
4

Polymorphism doesn't work like that.

Although a has a dynamic type B*, its static type is A* and as such the pointer to member operator -> cannot reach the printNew function.

Crudely, you could write

virtual void printNew() { cout << "printNew() not implemented";}

in class A.

From C++20 it might indeed be possible to do as you want using reflection, with albeit different calling syntax.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483