【问题标题】:Why doesn't derived class's function get called through base in PHP?为什么派生类的函数不通过 PHP 中的 base 调用?
【发布时间】:2015-10-09 00:07:41
【问题描述】:

我写了这个简单的例子来演示我的问题。我有一个基类和派生类。当我调用派生类的justdoit函数时,它不会调用派生类的doer函数,而是调用基类的doer函数。

预期输出:

Base::doer
Derived::doer

实际输出:

Base::doer
Base::doer

代码:

<?

class Base {
 public function justdoit() {
  $this->doer();
 }
 private function doer() {
  print "Base::doer\n";
 }
}

class Derived extends Base {
 private function doer() {
  print "Derived::doer\n";
 }
}

$b = new Base;
$b->justdoit();

$d = new Derived;
$d->justdoit();

?>

这是相同的 C++ 代码示例,它可以工作:

class A {
    public:
        void justdoit();
    private:
        virtual void doit();
};

void A::justdoit() {
    doit();
}

void A::doit() {
    std::cout << "A::doit\n";
}

class B : public A {
    private:
        virtual void doit();
};

void B::doit() {
    std::cout << "B::doit\n";
}

int main() {
 A a;
 B b;
 a.justdoit();
 b.justdoit();
}

输出:

A::doit
B::doit

有趣的是,如果我更改我原来的 PHP 示例并将 private function 替换为 protected function 它开始工作:

<?

class Base {
 public function justdoit() {
  $this->doer();
 }
 protected function doer() {
  print "Base::doer\n";
 }
}

class Derived extends Base {
 protected function doer() {
  print "Derived::doer\n";
 }
}

$b = new Base;
$b->justdoit();

$d = new Derived;
$d->justdoit();

?>

输出:

Base::doer
Derived::doer

有谁知道为什么 PHP 和 C++ 会产生不同的结果以及为什么在 PHP 中将 private 更改为 protected 会产生与 C++ 相同的结果?

【问题讨论】:

  • 顺便说一句:除非您正在寻找麻烦,否则不要使用短标签
  • @MarcinOrlowski 什么是短标签?从来没有听说过。 (对不起!)
  • PHP 中的短标签意味着使用&lt;? 而不是完整的&lt;?php
  • 你能解释一下为什么短标签不好?

标签: php c++ oop inheritance private


【解决方案1】:

请参阅What is the difference between public, private, and protected?,详细了解 PHP 中的公共、保护和私有。

这是我的看法:

函数justdoitBase 类中声明。当doerDerived 类中声明为private 时,它在Derived 类之外没有可见性,甚至对Base 类也不可见。因此,即使在Derived 的实例上执行justdoit,它也会执行Base 中的doer,因为这是它唯一可见的doer 函数。

【讨论】:

  • 那么它在 C++ 中是如何工作的呢?为什么同一个 OOP 代码示例会在两种不同的语言中产生两种不同的结果。
  • 您对virtual 的使用可能会解释这一点。据我了解,当您在 C++ 中声明函数 virtual 时,您是在指示该语言使用与签名匹配的最派生函数。
  • 这可以解释。你知道如何在 PHP 中制作虚函数来达到同样的效果吗?
【解决方案2】:

private 方法只能由该类访问。 protected 方法可以被子类访问。通过声明private function doer,您明确表示只有类的实例才能调用该函数。

Similar Question

【讨论】:

  • 谢谢,但是它如何在具有坚实 OOP 基础的 C++ 中工作?
  • @bodacydo 是什么让您认为 C++ 拥有“坚实的 OOP 基础”?
  • @imibis 我的意思是 C 没有 OOP,然后 C++ 添加了 OOP。
  • 一种不同的语言以不同的方式进行继承 - OMG!
【解决方案3】:

“那么它在 C++ 中是如何工作的呢?”

在您的 C++ 代码中,您调用的是函数的派生版本。

$d = new Derived;
$d->justdoit();

这段代码将调用“justdoit()”的派生版本,而不是基类,在 C++ 中,当我们创建虚函数时,会创建一个 vtable 来维护和保存被覆盖函数的地址,并且在调用,根据你用来调用的对象的类型,函数被调用。 这里,

$b = new Base;
$b->justdoit();

在这个块中,你正在使用基础对象,因此基础版本被调用。

希望您的问题得到解答。

【讨论】:

    猜你喜欢
    • 2021-02-01
    • 2022-07-01
    • 2011-09-16
    • 1970-01-01
    • 2020-10-27
    • 2013-11-30
    • 2016-10-06
    • 2010-12-24
    • 2012-10-04
    相关资源
    最近更新 更多