简体   繁体   English

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

[英]Access a string view of an object inside a vector of interfaces C++

I am storing different objects which inherit from the same interface inside a single vector.我将从单个向量中的同一接口继承的不同对象存储起来。 Those objects have their name stored as a constant string view, which gets its value even before the object gets instantiated.这些对象将它们的名称存储为常量字符串视图,甚至在对象被实例化之前就获取了它的值。 I am able to easily retrieve its name before it gets stored in a vector.在它存储在向量中之前,我能够轻松地检索它的名称。 However, when I store it inside a vector of interfaces and I access its name again, I get undefined behavior (compiler-dependent).但是,当我将它存储在一个接口向量中并再次访问它的名称时,我得到了未定义的行为(依赖于编译器)。 How can I fix this?我怎样才能解决这个问题?

Here's the simplest case which demonstrates my problem.这是证明我的问题的最简单的案例。 I'm using a compiler which supports C++17 and some features of C++20我正在使用支持 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;
    }
}

It produces the following results:它产生以下结果:

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

When I tried changing the vector to std::vector<Foo*> , the code ran without any problems.当我尝试将向量更改为std::vector<Foo*>时,代码运行没有任何问题。 However, this is not a solution, because I want to store multiple types which inherit from the same interface inside a single vector.但是,这不是解决方案,因为我想在单个向量中存储从同一接口继承的多种类型。

Data members can't be overridden.数据成员不能被覆盖。 Each name in the base and derived classes is a different member and which one you will name in an expression is determined from the static type of the object in the expression, which is IFoo if you iterate through the vector, but Foo when you refer to foo declared as Foo* .基类和派生类中的每个name都是一个不同的成员,您将在表达式中命名的成员取决于表达式中对象的静态类型,如果您遍历向量,则为IFoo ,而当您引用时,则为Foo foo声明为Foo*

Only virtual member function have polymorphic behavior.只有virtual成员函数具有多态行为。 So you need to use one instead:所以你需要改用一个:

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

It would also be a good idea to use std::unique_ptr<IFoo> and std::make_unique<Foo> instead of IFoo* and new Foo for memory and exception safety.为了内存和异常安全,使用std::unique_ptr<IFoo>std::make_unique<Foo>而不是IFoo*new Foo也是一个好主意。 (Then auto foo will need to be auto& foo instead.) (然后auto foo将需要改为auto& foo 。)

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

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