簡體   English   中英

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

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

我想在std::vector存儲具有相同基類的多個類。 經過一些研究,我很明顯我必須使用指針來防止對象切片。 但是,當我創建向量時,向其添加元素並返回它,結果向量沒有正確的值。

舉個例子,這是我的兩個類:

class Base {
    public:
        int var0;
}

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

這是一個簡單的print功能。 通常, 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;
    }
}

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));
    }
}

這打印:

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

現在,我希望這個向量由函數返回,所以我創建了一個函數:

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));
    }
}

這打印:

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

what I want. 我想要的。 我希望它像其他功能那樣打印。

有什么方法可以解決這個問題嗎? 也許任何方式可能做整個派生類的事情好一點?

您的程序行為未定義:

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

正在推回指向超出范圍的變量( b )的指針。

為什么不使用std::vector<std::unique_ptr<Base>>呢? 對象切片不會成為問題,向量將為您管理內存。

這與對象切片無關,而且與您在向量中存儲指向局部變量的指針有關。 一旦變量聲明的范圍已經結束,變量就會被破壞,留下亂碼指針,並且解除引用這些雜散指針會導致未定義的行為

在你說工作正常的程序中也有這個問題。 看似工作正常是一種或未定義行為的可能性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM