简体   繁体   English

从父 class 调用子的重写方法

[英]Calling child's overridden method from parent class

I want to practice C++ by coding a simple mobile phone application with an interchangeable system.我想通过使用可互换系统编写一个简单的手机应用程序来练习 C++。 I created a System base class and also created MyOS class which extends the System class. In the Phone class, I have a variable of System class because I think like in Java, you can assign it with child class. (eg. System sys = new MyOS();).我创建了一个系统基础class,还创建了MYOS class,该系统扩展了系统class。新的 MyOS();)。 But in C++ it calls the function in the base class.但在 C++ 中,它调用基数 class 中的 function。

What I want to work in C++ but it's in Java.我想在 C++ 工作,但它在 Java。

public class MyParent {
    public void start() {
        System.out.println("start() executed in MyParent");
    }
}

public class MyChild extends MyParent {
    @Override
    public void start() {
        System.out.println("start() excecuted in MyChild");
    }
}

public class Inherit {
    MyParent parent;
    
    public Inherit(MyParent parent) {
        this.parent = parent;
    }
    
    public void start() {
        parent.start();
    }
}

public class TestInherit {
    public static void main(String[] args) {
        Inherit i = new Inherit(new MyChild());
        i.start();
    }
}

Output: start() excecuted in MyChild

My current c++ code:我当前的 c++ 代码:

System.h系统.h

#pragma once

#include <iostream>

class System {
public:

    void start() {
        std::cout << "Booting System..." << std::endl;
    }
};

MyOS.h MyOS.h

#pragma once

#include <iostream>
#include "System.h"

class MyOS: public System {
public:

    // Override
    void start() {
        std::cout << "Booting MyOS..." << std::endl;
    }
};

Phone.h手机.h

#pragma once

#include "System.h"

class Phone {
public:

    Phone(System system) {
        Phone::system = system;
    }

    void start() {
        system.start();
    }

private:

    System system;
};

MyPhone.cpp MyPhone.cpp

#include "MyOS.h"
#include "Phone.h"
#include "System.h"

int main() {
    MyOS os;
    Phone myPhone(os);
    myPhone.start();

    return 0;
}

Output: Booting System...

There are 2 problems with your given code:您给定的代码有两个问题:

Problem 1问题1

The method start is a non-virtual member function so you're not actually overriding it in the MyOS .方法start是一个非虚拟成员 function 所以你实际上并没有在MyOS中覆盖它。

So first step is to make it virtual as shown below.所以第一步是使它虚拟化,如下所示。

Problem 2问题2

Moreover, in order for runtime binding to work, you must make the call to the virtual-member function using a pointer or a reference to the Base class(which is System ) object as shown below:此外,为了使运行时绑定起作用,您必须使用指针或对基类(即System ) object 的引用来调用虚拟成员 function ,如下所示:


Solution解决方案

Here we make sure that start is a virtual member function and also that the data member system is an lvalue reference to System so that dynamic binding can actually happen.这里我们确保start是一个虚拟成员 function 并且数据成员system是对System的左值引用,这样动态绑定才能真正发生。

MyOS.h MyOS.h

#pragma once

#include <iostream>
#include "System.h"

class MyOS: public System {
public:

    // Override
    public: void start() override {    //override keyword added here to make the intention clear
        std::cout << "Booting MyOS..." << std::endl;
    }
};

System.h系统.h

#pragma once

#include <iostream>

class System {
public:

    public:
//--vvvvvvv------------------->virtual keyword added here
    virtual void start() {
        std::cout << "Booting System..." << std::endl;
    }
};

Phone.h手机.h

#pragma once

#include "System.h"

class Phone {
public:

    Phone(System& psystem):system(psystem){
    }

    void start() {
        system.start();
    }

private:
//--------v----------->lvalue reference to System
    System& system;
};

main.cpp主.cpp

#include "MyOS.h"
#include "Phone.h"
#include "System.h"

int main() {
    MyOS os;
    Phone myPhone(os);
    myPhone.start();

    return 0;
}

The output of the above program is:上述程序的output为:

Booting MyOS...

Demo演示

Note笔记

Note that we can also make the data member system to be a pointer to a System object instead of making it an lvalue reference to a System object. Demo with pointer .请注意,我们还可以将数据成员system设为指向System object 的指针,而不是将其设为指向System object 的左值引用。带指针的演示 Also note in some circumstances, classes used as the root of an inheritance hierarchy should define a virtual destructor.另请注意,在某些情况下,用作 inheritance 层次结构根的类应该定义一个虚拟析构函数。 Refer to why virtual destructs are used.参考为什么使用virtual destructs。

If you're coming from java, you need to remember that every non-primitive variable or field in java is implicitly a pointer, so to make equivalent C++ code, you need to make all interclass references into pointers.如果您来自 java,则需要记住 java 中的每个非原始变量或字段都是隐式指针,因此要生成等效的 C++ 代码,您需要将所有类间引用都转换为指针。

In addition, every method in java is implicitly virtual, so if you want to override them, you need an explicit virtual in C++.另外,java中的每个方法都是隐式虚的,所以如果你想覆盖它们,你需要C++中的显式virtual

So you end up with something like:所以你最终会得到类似的东西:

#include <iostream>

class System {
public:

    virtual void start() {
        std::cout << "Booting System..." << std::endl;
    }
};

class MyOS: public System {
public:

    // Override
    void start() override {
        std::cout << "Booting MyOS..." << std::endl;
    }
};

class Phone {
public:

    Phone(System *system) {
        this->system = system;
    }

    void start() {
        system->start();
    }

private:

    System *system;
};

int main() {
    MyOS os;
    Phone myPhone(&os);
    myPhone.start();

    return 0;
}

Of course, using raw pointers is a recipe for memory leaks and corruption, as C++ does not have built in garbage collection.当然,使用原始指针会导致 memory 泄漏和损坏,因为 C++ 没有内置垃圾回收。 So you generally want to use "smart" pointers instead -- either std::unique_ptr or std::shared_ptr因此,您通常希望改用“智能”指针—— std::unique_ptrstd::shared_ptr

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM