0

我相信我有一个切片问题,我不知道如何解决它。我已将我实际程序中的问题总结为下面的示例。

#include <iostream>
#include <vector>
using namespace std;

class Base {
public:
    void Use(void) {
        cout << "Using Base :(\n";
    }
};

class First_Derived : public Base {
public:
    void Use(void) {
        cout << "Using First_Derived!\n";
    }
};

class Second_Derived : public Base {
public:
    void Use(void) {
        cout << "Using Second_Derived!\n";
    }
};

class A {
public:
    vector<Base *> Base_Objects;
};

class B {
public:
    vector<Base *> Base_Objects;
};


int main() {
    // Create and populate A_Object
    A A_Object;
    A_Object.Base_Objects.push_back(new First_Derived());
    A_Object.Base_Objects.push_back(new Second_Derived());

    // Create and populate B_Object with objects in A_Object.Base_Objects
    B B_Object;
    for (vector<Base *>::iterator i = A_Object.Base_Objects.begin(); i != A_Object.Base_Objects.end(); ++i) {
        B_Object.Base_Objects.push_back(*i);
    }

    // Run the Use() function for the first object in B_Object.Base_Objects
    (*B_Object.Base_Objects[0]).Use();

    // Get command terminal to pause so output can be seen on Windows
    system("pause");
    return 0;
}

输出是Using Base :(但我预期的Using First_Derived!。我认为问题在于,一旦First_Derived对象存储在Base_Objects向量中,它就会失去其独特的Use()功能,因为它正在转换为Base类型?有针对这个的解决方法吗?我尝试应用什么是对象切片?但我不相信我正确地应用它们。

4

2 回答 2

3

移动评论以回答

您的问题是您使用的是非虚拟函数(方法隐藏)而不是切片。

每当在子类中定义一个函数时,它都会在父类中“隐藏”相同方法的实现。

您要做的是将方法声明为虚拟的:

class Base {
public:
    virtual void Use(void) {
        cout << "Using Base :(\n";
    }
};

class First_Derived : public Base {
public:
    virtual void Use(void) {
        cout << "Using First_Derived!\n";
    }
};

class Second_Derived : public Base {
public:
    virtual void Use(void) {
        cout << "Using Second_Derived!\n";
    }
};

当我们讨论这个主题时,您可能还想声明虚拟析构函数。

当您尝试将子类存储在为父类分配的空间中时,就会发生切片。在这种情况下,父类的值只有足够的空间,所以孩子的被抛在后面。有趣的是,您通常只会在尝试访问成员时看到这一点……仍然会调用虚拟函数调用(vtable 将指向正确的方法调用)。切片会给你带来可怕的堆栈和堆损坏错误,并使值看起来很奇怪......“未定义的行为”,但它仍然会在类中调用正确的虚函数!

于 2014-10-22T19:50:00.847 回答
0

这不是切片问题。我想你只是打算Use成为virtual,但事实并非如此。

于 2014-10-22T19:47:41.703 回答