You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++:存储接口对象的vector中访问std::string_view出现未定义行为的解决方法

问题原因分析

你遇到的问题核心是基类与派生类的name成员属于独立变量,并未实现多态覆盖:C++中,当派生类声明了和基类同名的成员变量时,只会隐藏基类的成员,而非重写。因此通过IFoo*指针访问name时,实际读取的是基类IFoo中默认初始化的空std::string_view,而非派生类的"bar"值。

解决方案

最符合面向接口设计的方案是将name改为虚函数,利用C++多态机制实现正确的成员访问:

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

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

// 扩展其他派生类示例
struct AnotherFoo : public IFoo {
    std::string_view name() const override {
        return "another_foo";
    }
};

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());
    foos.push_back(new AnotherFoo());
    
    for (auto ptr : foos) {
        std::cout << "Name of object after storing: " << ptr->name() << std::endl;
    }
    
    // 手动释放内存避免泄漏
    delete foo;
    for (auto ptr : foos) {
        delete ptr;
    }
}

方案说明

  • 虚函数是C++多态的核心,通过基类指针调用时,会自动匹配实际指向的派生类重写版本,保证访问到正确的name值。
  • 字符串字面量的生命周期贯穿整个程序运行期,因此返回std::string_view不会出现悬空引用问题,完全满足你"name在实例化前已确定"的需求。
备选方案(非虚函数实现)

如果不想使用虚函数,也可以通过基类构造函数传递name值,让派生类在构造时初始化基类成员:

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

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

struct Foo : public IFoo {
public:
    Foo() : IFoo("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 ptr : foos) {
        std::cout << "Name of object after storing: " << ptr->name << std::endl;
    }
    
    delete foo;
    for (auto ptr : foos) {
        delete ptr;
    }
}

这种方式的缺点是灵活性较低,每个派生类都需要编写构造函数传递name值,且无法动态修改name(若有此类需求)。

内容的提问来源于stack exchange,提问作者Frogieder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:35:27