当我在子类中调用函数时,它是在调用父类函数

时间:2019-04-24 22:55:46

标签: c++ c++11 inheritance override

我正在一个项目中,我有一系列子类。 我想从数组中调用一个重写的子函数,但是它调用了父函数。

#include <iostream>

class Parent {
public:
    Parent(){}
    void print() {
        std::cout << "I'm the parent!" << std::endl;
    }
};

class ChildOne : public Parent {
public:
    ChildOne(){}
    void print() {
        std::cout << "I'm childOne!" << std::endl;
    }
};

class ChildTwo : public Parent {
public:
    ChildTwo() {}
    void print() {
        std::cout << "I'm childTwo!" << std::endl;
    }
};


int main(int argc, char const *argv[]) {
    Parent arr[] = {ChildOne(), ChildTwo()};
    int n = 2;

    for(int i = 0; i < n; i++) {
        arr[i].print();
    }

    return 0;
}

我得到的输出是

I'm the parent!
I'm the parent!

我想要的输出是

I'm childOne!
I'm childTwo!

4 个答案:

答案 0 :(得分:3)

将实例存储在该类型数组中时,您将隐式将所有实例强制转换为类型Parent。由于您使用的是静态分派,因此您总是要使用(隐式)向下转换为的基本类型来调用该方法。

答案 1 :(得分:2)

您的代码遇到两个问题:

  1. 您实际上根本没有覆盖print(),因为它不是virtual。因此,您只是在每个子类中超载隐藏父类的方法。

  2. 将它们存储到数组中时,您是slicing your objects。因此,print()是否为虚拟并不重要,因为数组中没有子对象,只有父对象。仅当使用对基类的指针/引用时,多态性才能正常工作。

尝试以下方法:

#include <iostream>

class Parent {
public:
    Parent(){}
    virtual void print() {
        std::cout << "I'm the parent!" << std::endl;
    }
};

class ChildOne : public Parent {
public:
    ChildOne(){}
    void print() override {
        std::cout << "I'm childOne!" << std::endl;
    }
};

class ChildTwo : public Parent {
public:
    ChildTwo() {}
    void print() override {
        std::cout << "I'm childTwo!" << std::endl;
    }
};

int main() {
    ChildOne c1;
    ChildTwo c2;
    Parent* arr[] = {&c1, &c2};

    int n = 2;
    for(int i = 0; i < n; i++) {
        arr[i]->print();
    }

    return 0;
}

答案 2 :(得分:2)

首先,Parent的成员函数必须为virtual

class Parent
{
   public:
       Parent(){}
       virtual void print() {std::cout << "I'm the parent!" << std::endl;};
};

然后,孩子需要覆盖它。在C ++ 11和更高版本中,建议使用override

class ChildOne : public Parent
{
   public:
      ChildOne(){}
      void print() override {std::cout << "I'm childOne!" << std::endl;};
};

要解决的第二件事是您在main()中的代码

Parent arr[] = {ChildOne(), ChildTwo()};

通过切片初始化两个Parent对象,即arr[0]arr[1]都是Parent类型,而不是ChildOneChildTwo类型。

要解决此问题,arr必须是一个指针数组,并进行相应的初始化。

 Parent *arr[] = {new ChildOne(), new ChildTwo()};

,可以跟着

for(int i = 0; i < 2; i++)
{
    arr[i]->print();
}

for(int i = 0; i < 2; i++)    // to avoid a memory leak
{
    delete arr[i];
}
//  don't use elements of `arr` here

更好的方法(C ++ 11和更高版本)是编写main()是使用标准标头std::unique_ptr中的<memory>

std::unique_ptr<Parent> arr[] = {new ChildOne(), new ChildTwo()};

允许取消循环以释放arr的元素。在C ++ 14和更高版本中,可以使用arr创建std::make_unique()中的对象。

答案 3 :(得分:1)

您需要将父函数指定为virtual,子函数应使用override关键字。

class Parent {
public:
    Parent(){}
    virtual void print() {
        std::cout << "I'm the parent!" << std::endl;
    }
};

class ChildOne : public Parent {
public:
    ChildOne(){}
    void print() override {
        std::cout << "I'm childOne!" << std::endl;
    }
};

class ChildTwo : public Parent {
public:
    ChildTwo() {}
    void print() override {
        std::cout << "I'm childTwo!" << std::endl;
    }
};