C++ Inheritance: Derived class pointer to a Base class invokes Derived class method

前端 未结 6 1787
眼角桃花
眼角桃花 2021-01-25 20:28

I am learning C++ inheritance, so I tried this code by creating a Base class dynamically and made a downcast to its Derived class (obviously its not valid to downcast) in order

6条回答
  •  闹比i
    闹比i (楼主)
    2021-01-25 20:54

    The reason your code behaves this way is probably because the compiler doesn't check the actual type of your object (it isn't required to unless your function is virtual); it just calls child::who because you told it to. That said, your code is certainly suspect.

    You are statically downcasting the base class pointer to a derived class pointer, which not type-safe. C++ will not prevent you from doing this; it is up to you to ensure that your pointer really does point to an object of the derived type. Dereferencing the pointer if it does not refer to an object of the derived type is potentially undefined behaviour. You are lucky your code even prints anything at all.

    You need to make sure your base class function who is virtual, otherwise the function call will not behave polymorphically. Keep in mind, once you add virtual to your code, you will certainly be invoking undefined behaviour, because you are illegally downcasting to an invalid type. You can safely downcast using dynamic_cast, which will return a nullptr if the object is not of the specified type.

    You should also generally have a virtual destructor in your base class, so that your object can be deleted polymorphically. Speaking of which, you also need to make sure to delete your dynamically allocated object at some point. By manually calling new and delete, it is very easy to leak memory like this, even if you know that you need to call delete. std::unique_ptr and std::shared_ptr were added to the standard library in C++11 to address these concerns. Use these instead of new and delete in all but the most low-level code.

    To summarize, here is how I suggest your code should look:

    #include 
    #include 
    
    class parent {
        public:
            virtual ~parent() {}
    
            virtual void who() {
                std::cout << "I am parent";
            }
    };
    
    class child : public parent {
        public:
            void who() override {
                std::cout << "I am child";
            }
    };
    
    int main() {
        auto p = std::make_unique();
        auto c = dynamic_cast(p.get());
    
        if (c) // will obviously test false in this case
        {
            c->who();
        }
    }
    

提交回复
热议问题