1

  Using the base class pointer can reach the derived class content, in general,I think. Maybe I think it is like a train, as long as I find the head of it,I can reach all of them which is public.

  However, when I try to do something like this, I got an error that the base class cannot find the derived class's member function. Although I use a base class pointer variable to record the derived class address, I think it can also reach derived class member function with the head of train. While the fact proved it cannot. So I wonder what the design idea of it. Why it is designed not like Python can do? What is the advantage of this design idea?

The error is prompted as blow: enter image description here

Sketch map:

enter image description here

Demo code:

#include <iostream>

using namespace std;


class B{
public:
    void helloB(){
        cout << "hello B" << endl;
    }
};


class C:public B{
public:
    void helloC(){
        cout << "hello C" << endl;
    }
};

class A{
public:
    B* t;
    void helloA(){
        t->helloC();
    }
};

int main(){
    A a;
    C c;
    a.t = &c;
    a.helloA();
}
Franco
  • 123
  • 11

4 Answers4

5

Why?

C++ is statically typed language. That is, it does type-checking at compilation time, not at runtime.

At compilation time, the compiler has no way of knowing that t (which it knows to have type B*) has a helloC method. The language is trying to prevent you from shooting yourself in the foot by invoking undefined behavior if the method doesn't exist.

In contrast, Python is a dynamic language that does not have static type checking.

There are tradeoffs from static- vs. dynamic-checking. Dynamic-checking is more flexible but usually means that you can't catch some errors unless you exercise all code paths at runtime. Static-checking helps catch errors early and allows for better optimized (i.e. faster) code. For example, when invoking A::helloA, if B::helloC existed, your program would not need to check first whether t has a helloC method; it would already have been proven at compilation time.

C++ is statically typed because its target audience are developers who want to optimize for speed.

In C++, what can you do instead?

To avoid this in C++, you instead must push your interface into the base class and make it a virtual method or perform a downcast to force a pointer (or reference) to a base class to be treated as a pointer/reference to the derived class. In this case, you could use static_cast:

void helloA(){
    static_cast<C*>(t)->helloC();
}

which tells the compiler that you know with absolute certainty that t is actually a C*. This will add no runtime overhead, but no runtime overhead also means that there is no runtime checking that t is actually a C*.

A more general way to downcast is to use dynamic_cast:

void helloA(){
    C* c = dynamic_cast<C*>(t);
    if (c != null) {
      c->helloC();
    }
}

which will check at runtime whether t is actually a C*. Runtime checks have a runtime cost, of course.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
0

Well, the compiler doesn't know anything about the object in question other than it's an instance of class B. You could have some other classes derived from B and they will fit everywhere class B can fit. Consider this: class B is more general thing (let's say an animal), while class C or any other class derived from B is some kind of animal. Let's say a dog or a bird. Let's assume all animals can make a noise, but only birds can lay an egg. Now you can have a set of animals and tell them all to make a sound, but you can't tell all of them to lay an egg. The compiler doesn't have an idea of egg-laying animal on this abstraction level. In your code the compiler can't be sure you're talking about an instance of class C.

vrtex
  • 165
  • 9
0

My friend, you need to read a bit about inheritance in c++ or at least difference between c++ and python for inheritance.

From your example, it looks like you are asking a dog say Meow :D

Abhinav
  • 1,496
  • 3
  • 15
  • 31
0

Class C inherits from class B, not the other way, so method helloC, which is from class C, can't be called from an object of class B.