Home  >  Q&A  >  body text

C++居然能用父类指针(里面存的也是父类)调用子类(子类独有的)函数?

昨天问另外一个问题的时候, 今天早上有人回复给出了这样一段代码, 我试着运行了一下, 结果却大大出乎我的意料 :

class Father
{
public:
    virtual void func1() { std::cout << "Father" << std::endl; }
    virtual ~Father(){}
};
class Son :public Father
{
public:
    virtual void func1(){ std::cout << "Son1" << std::endl; }
    void func2(){ std::cout << "Son2" << std::endl; }
    virtual ~Son(){}
};
class Factory
{
private:
    Father* myFather;
public:
    void setFun(Father* m_Father) { myFather = m_Father; }
    Father* getFun() { return myFather;};
};

int main()
{
    Father *m_Father = new Father();
    Factory* m_Factory = new Factory();
    m_Factory->setFun(m_Father );
    m_Factory->getFun()->func1();
    dynamic_cast<Son*>(m_Factory->getFun())->func2();
    ///
    return 0;
}

运行结果是 :

Father
Son2

这让我感觉特别的奇怪 :
首先对于main中的变量m_Father, 他的静态类型和动态类型都是Father指针, 之后使用dynamic_cast<Son*>进行强制转换, 按照我的设想, 只有当m_Father的动态类型, 也就是实际指向一个Son的时候, 转换才能够成功, 然而这里不但成功转换, 同时还调用了Son独有的函数fun2, 这不是太奇怪了吗?

伊谢尔伦伊谢尔伦2713 days ago506

reply all(4)I'll reply

  • PHPz

    PHPz2017-04-17 14:23:02

    You try adding a data member to the subclass and printing it when func is called.

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-17 14:23:02

    You have to understand that in C++, the member functions of a class are not essentially different from the functions in C. They are just a piece of code in memory. The same goes for fun2 here. When you change the pointer to Son* type and you call (Son*)->func2(), C++ will only spell it into a function signature like Son$func2..., and then go to the symbol table to check the function signature. Corresponding memory location, and then execute the function

    In the program, dynamic_cast<Son*>(m_Factory->getFun()) is not converted successfully, it is a null pointer, but the member function can still be called on the null pointer, because the addressing is successful

    reply
    0
  • 黄舟

    黄舟2017-04-17 14:23:02

    In the object instance of the class, only member variables are stored in the memory layout. If there is a virtual, a vptr will be added, and the member functions of the class are stored separately.
    If the class in a piece of code does not have any member variables and does not involve virtual functions, even if you call it with a class pointer pointing to NULL, it will still succeed. This is similar to calling a function in C language.

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-17 14:23:02

    At first glance, it looks like a patient poisoned by the syntactic sugar of C++, haha. For these two classes, they actually inherit the father class. Essentially, it just contains a pointer to father. Coercion is a union based on the conversion object. So only the attributes in son are taken as the converted attributes. And they both inherited father, so the conversion is no problem

    reply
    0
  • Cancelreply