+ -
当前位置:首页 → 问答吧 → 关于构造函数在面向对象的继承中与普通成员函数的区别

关于构造函数在面向对象的继承中与普通成员函数的区别

时间:2012-11-20

来源:互联网

最近终于开始新的工作了,老婆说因为11月对于白羊座而言运势不太旺,所以找了很久的工作,遇到很多很傻的公司,
anyway,all is well
回到正题,首先声明我也不知道我自己理解的对不对,只是记录下来,请高手来指点的,
今天在看代码的时候发现,子类如果不写构造函数,那么父类的构造函数会被默认调用,这个大家都知道,今天我惊奇的发现,new 子类的时候的参数,也会被传到父类的构造函数中去,如果是java之类的强类型语言,那么只会调用默认构造函数,无参的那个,
然后就和朋友聊起来这个了,我们争论,究竟是子类继承了父类的构造函数,一如普通的成员函数那样,还是,在内部,没有发现构造函数的时候,子类自动的调用了父类的构造函数,并把参数传递进去,可能有点拗口,但是我觉得这里面的区别还是很大的,
所以大家就开始各自证明自己是对的,
于是我开始找源码,发现,似乎构造函数在继承的时候,父类的构造函数会被zend_hash_update更新到子类的function_table里面去,但是普通成员方法就没有这一步,最后大家都会被function_add_ref(**zend_function function),这个应该是为新的函数指针复制一份静态变量(因为调用子类对象中继承自父类的方法和直接从父类对象调用该方法是不一样的)
最后附上的是php里面的源码,

这是方法继承的代码
static void do_inherit_method(zend_function *function) /* {{{ */
{
        /* The class entry of the derived function intentionally remains the same
         * as that of the parent class.  That allows us to know in which context
         * we're running, and handle private method calls properly.
         */
        function_add_ref(function);
}
/* }}} */


这是关于构造函数的代码
static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
{
        zend_function *function, *new_function;

        if (!ce->parent) {
                return;
        }

        /* You cannot change create_object */
        ce->create_object = ce->parent->create_object;

        /* Inherit special functions if needed */
        if (!ce->get_iterator) {
                ce->get_iterator = ce->parent->get_iterator;
        }
        if (!ce->iterator_funcs.funcs) {
                ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
        }
        if (!ce->__get) {
                ce->__get   = ce->parent->__get;
        }
        if (!ce->__set) {
                ce->__set = ce->parent->__set;
        }
        if (!ce->__unset) {
                ce->__unset = ce->parent->__unset;
        }
        if (!ce->__isset) {
                ce->__isset = ce->parent->__isset;
        }
        if (!ce->__call) {
                ce->__call = ce->parent->__call;
        }
        if (!ce->__callstatic) {
                ce->__callstatic = ce->parent->__callstatic;
        }
        if (!ce->__tostring) {
                ce->__tostring = ce->parent->__tostring;
        }
        if (!ce->clone) {
                ce->clone = ce->parent->clone;
        }
        if(!ce->serialize) {
                ce->serialize = ce->parent->serialize;
        }
        if(!ce->unserialize) {
                ce->unserialize = ce->parent->unserialize;
        }
        if (!ce->destructor) {
                ce->destructor   = ce->parent->destructor;
        }
        if (ce->constructor) {
                if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
                        zend_error(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
                                ce->parent->name, ce->parent->constructor->common.function_name,
                                ce->name, ce->constructor->common.function_name
                                );
                }
                return;
        }

        if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
                /* inherit parent's constructor */
                zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), (void**)&new_function);
                function_add_ref(new_function);
        } else {
                /* Don't inherit the old style constructor if we already have the new style constructor */
                char *lc_class_name;
                char *lc_parent_class_name;

                lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
                if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
                        lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
                        if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) &&
                                        zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
                                if (function->common.fn_flags & ZEND_ACC_CTOR) {
                                        /* inherit parent's constructor */
                                        zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), (void**)&new_function);
                                        function_add_ref(new_function);
                                }
                        }
                        efree(lc_parent_class_name);
                }
                efree(lc_class_name);
        }
        ce->constructor = ce->parent->constructor;
}
/* }}} */

作者: kylidboy   发布时间: 2012-11-20

看明白了,是来晒老婆的。元芳你觉得呢?

作者: hmly   发布时间: 2012-11-21