简体   繁体   English

c ++阻止std :: vector中的对象切片

[英]c++ prevent object slicing in std::vector

I would like to store multiple classes with the same base class in a std::vector . 我想在std::vector存储具有相同基类的多个类。 After some research, it became apparent to me that I have to use pointers to prevent object slicing. 经过一些研究,我很明显我必须使用指针来防止对象切片。 However, when I create the vector, add elements to it and return it, the resulting vector doesn't have the right values. 但是,当我创建向量时,向其添加元素并返回它,结果向量没有正确的值。

As an example, here are my two classes: 举个例子,这是我的两个类:

class Base {
    public:
        int var0;
}

class Derived : public Base {
    public:
        int var1;
}

And here is a simple print function. 这是一个简单的print功能。 As a rule, all instances of Base should have var0 == 23 , and all instances of Derived should have var0 != 23 . 通常, Base所有实例都应该具有var0 == 23 ,并且Derived所有实例都应该具有var0 != 23

void print(Base& value) {
    if (value.var0 == 23) {
        std::cout << "Base: " << value.var0 << std::endl;
    } else {
        Derived d = (Derived&) value;
        std::cout << "Derived: " << d.var0 << ", " d.var1 << std::endl;
    }
}

First of all, this does work like I want it to: 首先,这确实像我想要的那样:

int main() {
    int num = 10;
    std::vector<Base*> vec;

    for (int i = 0; i < num; i++) {
        if (i % 2 == 0) {
            Base b;
            b.var0 = 23;
            vec.push_back(&b);
        } else {
            Derived d;
            d.var0 = 17;
            d.var1 = 42;
            vec.push_back(&d);
        }
    }

    // ....

    for (int i = 0; i < num; i++) {
        print(*vec.at(i));
    }
}

This prints: 这打印:

Base: 23
Derived: 17,42
Base: 23
Derived: 17,42
Base: 23
Derived: 17,42
Base: 23
Derived: 17,42
Base: 23
Derived: 17,42

Now, I want this vector to be returned by a function, so I create a function: 现在,我希望这个向量由函数返回,所以我创建了一个函数:

std::vector<Base*> createVector(int num) {
    std::vector<Base*> vec;

    for (int i = 0; i < num; i++) {
        if (i % 2 == 0) {
            Base b;
            b.var0 = 23;
            vec.push_back(&b);
        } else {
            Derived d;
            d.var0 = 17;
            d.var1 = 42;
            vec.push_back(&d);
        }
    }

    return vec;
}

int main() {
    int num = 10;
    std::vector<Base*> vec = createVector(num);

    // ....

    for (int i = 0; i < num; i++) {
        print(*vec.at(i));
    }
}

This prints: 这打印:

Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42

Which is not what I want. 不是我想要的。 I want it to print like the other function did. 我希望它像其他功能那样打印。

Is there any way to solve this problem? 有什么方法可以解决这个问题吗? Any way to maybe do the whole derived-class thing a bit better? 也许任何方式可能做整个派生类的事情好一点?

Your program behaviour is undefined: 您的程序行为未定义:

Base b;
b.var0 = 23;
vec.push_back(&b);

is pushing back a pointer to a variable ( b ) that goes out of scope. 正在推回指向超出范围的变量( b )的指针。

Why not use a std::vector<std::unique_ptr<Base>> instead? 为什么不使用std::vector<std::unique_ptr<Base>>呢? Object slicing will not be an issue, and the vector will manage the memory for you. 对象切片不会成为问题,向量将为您管理内存。

This has nothing to do with object slicing, and everything to do with you storing pointers to local variables in the vector. 这与对象切片无关,而且与您在向量中存储指向局部变量的指针有关。 Once the scope the variables were declared in has ended, the variables are destructed leaving you with stray pointers, and dereferencing these stray pointers leads to undefined behavior . 一旦变量声明的范围已经结束,变量就会被破坏,留下乱码指针,并且解除引用这些杂散指针会导致未定义的行为

You have this problem also in the program that you says work fine. 在你说工作正常的程序中也有这个问题。 Seemingly working fine is one or the possibilities of undefined behavior. 看似工作正常是一种或未定义行为的可能性。

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

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