使用父类型时覆盖C ++方法

时间:2015-02-05 16:50:54

标签: c++ vector override

Heyo,当你将调用对象作为父类型时,我对方法重写的工作原理有点困惑。

这是我的示例代码:

#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;

class A {
public:
    A() {
        std::cout << "Made A.\n";
    }
    void doThing() {
        std::cout << "A did a thing.\n";
    };
};

class B : public A {
public:
    B() {
        std::cout << "Made B.\n";
    }
    void doThing() {
        std::cout << "B did a thing.\n";
    };
};

class C : public A {
public:
    C() {
        std::cout << "Made C.\n";
    }
    void doThing() {
        std::cout << "C did a thing.\n";
    };
};

int main(int argc, char** argv) {
    std::cout << "\n";

    std::cout << "Make objects: \n";
    A a;
    B b;
    C c;

    std::cout << "Call objects normally: \n";
    a.doThing();
    b.doThing();
    c.doThing();

    std::cout << "Call objects as their parent type from a vector: \n";
    vector<A> vect;
    vect.push_back(a); vect.push_back(b); vect.push_back(c);

    for(int i=0;i<vect.size();i++)
        vect.data()[i].doThing();

    return 0;
}

这是我得到的输出:

Make objects: 
Made A.
Made A.
Made B.
Made A.
Made C.
Call objects normally: 
A did a thing.
B did a thing.
C did a thing.
Call objects as their parent type from a vector: 
A did a thing.
A did a thing.
A did a thing.

另一种语言(如Java)中的相同代码会生成此输出:

Make objects: 
Made A.
Made B.
Made C.
Call objects normally: 
A did a thing.
B did a thing.
C did a thing.
Call objects as their parent type from a vector: 
A did a thing.
B did a thing.
C did a thing.

简而言之,我如何在c ++中实现第二个输出?

3 个答案:

答案 0 :(得分:1)

您需要使用virtual关键字来启用在子类中覆盖的函数。

答案 1 :(得分:1)

每当您将Derived对象按值传递给采用Base的函数时,就会发生称为“切片”的事件。基本上,只使用Base对象的Derived部分。

您需要通过引用或指针传递对象以避免这些问题。例如,声明

f(Base&)

允许传入Derived对象,即允许您编写

f(Derived)

此外,要启用运行时多态性,必须将您的函数标记为virtual。默认情况下,Java将所有内容隐式标记为虚拟。但是,这是C ++,你不支付你不使用的东西(虚函数是一个开销)。

PS:在你的代码中,即使你想要,你也不能使用std::vector引用。但是,您可以使用std::reference_wrapper来包装对象,这允许您“模拟”std::vector个引用:

std::vector<std::reference_wrapper<A>> vect

并使用get成员函数检索引用

for(int i=0;i<vect.size();i++)
    vect[i].get().doThing();

或者,或许更简单,只需使用std::vector<A*>

答案 2 :(得分:1)

好的,这就是发生的事情: 制作物品: 我认为A非常明显。构造A对象并打印其默认构造函数

Made A

首先实例化B对象时,其父类将完全构造。所以在这种情况下,父类是A,它使用默认构造函数构造,打印出

Made A 

之后,B类剩余部分被构造并运行其打印输出的构造函数

Made B

实例化C

时会发生同样的事情

调用对象上的函数: 它只是一个简单的函数调用,因为你在每个类中覆盖它们被调用的函数而不是父函数。

当您创建对象的矢量时,您将对象复制到它们中,因为您不传递引用也不传递指针。您还没有编写复制构造函数,因此将运行默认的逐位复制。这样从B类对象中你得到一个A类对象,该函数将打印出A做的事情而不是B做的事情。 C也是如此。