【问题标题】:How does C++ knows child class calls a parent method?C++ 如何知道子类调用父方法?
【发布时间】:2020-01-26 04:17:50
【问题描述】:

我不知道如何总结我的问题,所以在 Google 上找不到答案。

重写父方法时,

void Child::method(){
    //stuff
    Parent::method();
}

完美运行。但是父方法需要来自 Child 类实例的信息才能正常工作,这不是作为参数给出的。所以我的问题是,C++ 是否有一种机制让 Parent 知道 Child 类的哪个实例调用 Parent 方法,比如 而不Parent::method(this)

让我想到的是,如果你这样做,

int main(){
    SomeParentClass::someMethod();
}

它给出:错误:在没有对象参数的情况下调用非静态成员函数。因此编译器需要知道子类中没有给出的实例。但没有引发错误,所以它一定知道实例。

编辑:我添加了 Qt 标签,因为我正在尝试 Qt 类。如果需要,我可以举个例子。

编辑2:

devicedialog.h

class DeviceDialog : public QDialog
{
    Q_OBJECT

public:
    explicit DeviceDialog(QWidget *parent = nullptr);
    int exec() override;
    ~DeviceDialog() override;
}

devicedialog.cpp

int DeviceDialog::exec(){
    // My code.
    return QDialog::exec();
}

exec() 函数激活并在屏幕上显示一个 QDialog。但是,以这种方式调用它,似乎父方法无法知道要显示哪个对话框(没有传递参数)。唯一的知识可能是调用它的实例的身份。我只是问这些知识是否转移到后台的方法中。

【问题讨论】:

  • C++ 是否有一种机制让 Parent 知道 Child 类的哪个实例调用 Parent 方法 -- 这种机制被称为“好设计”。您需要澄清或更详细地解释这意味着什么——但父方法需要来自 Child 类实例的信息才能正常工作
  • @PaulMcKenzie 请检查编辑。
  • 之前没有调用函数来“设置父级”并提供信息吗?这就是父母“了解孩子”的明显原因。 exec() 之前的子对象为父对象提供了信息。
  • @PaulMcKenzie 似乎没有。唯一的事先声明是devicedialog.cpp 中的DeviceDialog::DeviceDialog(QWidget *parent) : QDialog(parent), ui(new Ui::DeviceDialog)。但是父级是 nullptr 或 MainWindow(取决于选择),Ui 调用只影响子级。
  • 没有“知道父级”的 C++ 语法。这都是你使用的任何东西的内部设计的一部分,你只需要更仔细地了解它为什么会以它的工作方式工作。没有魔法发生——你只是没有看到它。您之前提出这种语法的尝试表明这只是一个设计问题,而不是语法问题。

标签: c++ qt c++11 inheritance


【解决方案1】:

这仍然是一个 c++ 特定的问题。 Qt 只是利用它。您需要研究对象、继承和虚拟方法。

void Child::method() {
  Parent::method();
  // this->Parent::method();
}

上面的工作是因为孩子可以访问父母的方法(不是私有的)。因为该方法是对父虚拟方法的覆盖,所以编译器知道您要调用父方法的唯一方法是在子中使用范围解析“::”来调用它。

int main() {
  SomeParentClass::someMethod();
}

上述方法不起作用,因为没有实例化对象。当你调用一个方法时,你在对象上调用它(除非它是一个静态方法)。因此,您可以这样做:

int main() {
  SomeParentClass parent;
  parent.someMethod();

  ChildClass child;
  child.someMethod(); // accesses the childs overridden method and not the parents.
}

【讨论】:

  • 我猜别人是在我玩游戏时打字的时候回答的。
【解决方案2】:

这对于父类的成员函数来说没什么特别的。通过显式命名类型来调用子类的函数:

Child::method();

在这方面的工作方式完全相同。在成员函数定义之外使用它会导致相同的错误。

标准的相关段落是§9.3.1:

当 id 表达式不属于类成员访问语法时 并且不用于形成指向成员的指针,用于类的成员 X 在可以使用 this 的上下文中,如果名称查找解析 id-expression 中的 name 到 some 的非静态非类型成员 C 类,如果 id 表达式可能被评估或 C 是 X 或 X 的基类,则 id 表达式转换为 使用 (*this) 作为后缀表达式的类成员访问表达式 的左侧。运算符。

也就是说,调用

Parent::method();

在成员函数内部被转换成类似于

(*this).Parent::method();

【讨论】:

    【解决方案3】:

    我认为您只是对语言试图让您更轻松的尝试感到困惑。您的示例函数相当于

    void Child::method(){
        //stuff
        this->Parent::method();
    }
    

    正如你不能在没有对象的情况下调用子类中的(非静态)方法一样,你不能在没有对象的情况下调用父类的方法。但是,上下文是这种方法的主体。在正文中,上下文假定为*this。正如您可以在不显式添加“this->”前缀的情况下引用数据成员一样,您也可以调用不带前缀的方法。

    【讨论】:

    • 我实际上是在问这个。 parent 调用对我来说似乎模棱两可,因为 Parent 有自己的声明。
    • 什么是歧义? Parent::method() 可以引用多个函数吗?
    • 不是方法。但是 parent.h 导入的 Parent 名称让我很困惑。看起来像调用全局名称而不是 this->Parent 的孩子。
    • 对不起,我不明白你说的“parent.h导入的父名”“全局名”是什么意思。跨度>
    • 鉴于Parent类在parent.h中声明,当#include'd时,全局类名Parent 被导入到当前脚本。我以为从子类调用它时,它们会发生冲突,或者没有想到父名称的本地范围。
    猜你喜欢
    • 1970-01-01
    • 2016-02-14
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 2012-01-21
    • 2021-04-03
    • 1970-01-01
    相关资源
    最近更新 更多