访问接口向量中对象的字符串视图C++

9avjhtql  于 2022-12-20  发布在  其他
关注(0)|答案(1)|浏览(136)

我将从同一接口继承的不同对象存储在一个向量中。这些对象的名称存储为常量字符串视图,该视图甚至在对象示例化之前就获得其值。我能够在将其存储在向量中之前轻松检索其名称。然而,当我将其存储在接口向量中并再次访问其名称时,我得到了未定义的行为(依赖于编译器)。我该如何解决这个问题?
这里有一个最简单的例子来说明我的问题。我使用的编译器支持C++17和C ++20的一些特性

#include <string_view>
#include <vector>
#include <iostream>

struct IFoo {
public:
    virtual ~IFoo() = default;
    const std::string_view name{};
};

struct Foo : public IFoo {
public:
    const std::string_view name = "bar";
};

int main() {
    std::vector<IFoo*> foos;
    Foo *foo = new Foo();
    std::cout << "Name of object before storing: " << foo->name << std::endl;
    foos.push_back(new Foo());
    for (auto foo : foos) {
        std::cout << "Name of object after storing: " << foo->name << std::endl;
    }
}

它产生以下结果:

Name of object before storing: bar
Name of object after storing:

当我尝试将向量更改为std::vector<Foo*>时,代码运行没有任何问题,但是,这不是一个解决方案,因为我想将从同一接口继承的多个类型存储在一个向量中。

enyaitl3

enyaitl31#

数据成员不能被重写。基类和派生类中的每个name都是不同的成员,在表达式中命名哪个成员取决于表达式中对象的静态类型,如果迭代向量,则为IFoo,但如果引用声明为Foo*foo,则为Foo
只有virtual成员函数有多态行为,所以你需要使用一个:

struct IFoo {
public:
    virtual ~IFoo() = default;
    virtual std::string_view name() const = 0;
};

struct Foo : public IFoo {
public:
    std::string_view name() const override {
        return "bar";
    }
};

//...

for (auto foo : foos) {
    std::cout << "Name of object after storing: " << foo->name() << std::endl;
}

为了内存和异常安全,使用std::unique_ptr<IFoo>std::make_unique<Foo>而不是IFoo*new Foo也是一个好主意(那么auto foo就需要改为auto& foo)。

相关问题