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

C++非静态成员引用错误:GetName函数调用问题求助

解决 "a nonstatic member reference must be relative to a specific object" 错误

嗨,这个问题的根源其实很清晰:你在静态成员函数里直接调用了非静态的GetName方法。静态函数属于整个类,不依附于任何具体的对象实例,所以它没法直接调用那些需要对象才能运行的非静态成员函数——编译器根本不知道该用哪个Exchanger_npc对象来执行GetName,自然就抛出这个错误了。

具体问题拆解

你的OnGossipHello和OnGossipSelect都是标记为static的函数,但GetName是Exchanger_npc类里的普通成员函数。当静态函数尝试调用GetName时,因为没有对应的对象实例,编译器就懵了,于是报错。

两种修复方案(推荐第一种)

方案1:把GetName改成静态成员函数

看GetName的实现,它只用到了全局的sObjectMgr,完全不需要访问Exchanger_npc类的任何实例成员,所以直接把它改成静态函数就搞定了:

static std::string GetName(uint32 entry)
{
    // 建议加个空指针检查,避免无效物品ID导致崩溃
    ItemTemplate const* itemTemp = sObjectMgr->GetItemTemplate(entry);
    return itemTemp ? itemTemp->Name1 : "Unknown Item";
};

这样静态的OnGossipHello和OnGossipSelect就能直接调用它,编译器也不会有意见了。

方案2:传入类实例调用(不推荐)

如果因为某些原因不能把GetName改成静态,那你得在调用时提供一个Exchanger_npc的对象实例。不过你的场景里OnGossipHello是静态的,没有现成的实例引用,这种方式会很麻烦,所以更推荐方案1。

修改后的完整代码(关键部分已修正)

我还顺便调整了MyAI的位置,把它放到了Exchanger_npc的私有域里,更符合类封装的规范,同时明确了静态函数的调用路径:

#include "ScriptMgr.h"
#include "Creature.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "WorldSession.h"

struct tokenData {
    uint32 TAKE_ENTRY, TAKE_AMOUNT, GIVE_ENTRY, GIVE_AMOUNT;
};

struct tokenData Tokens[] = {
    {191201, 10, 191202, 1},
    {191202, 1, 191201, 10},
    {191202, 25, 191203, 1},
    {191203, 1, 191202, 25},
    {191203, 50, 191204, 1},
    {191204, 1, 191203, 50},
    {191204, 100, 191205, 1},
    {191205, 1, 191204, 100}
};

const uint32 tokensSize = sizeof Tokens / sizeof(*Tokens);

class Exchanger_npc : public CreatureScript {
public:
    Exchanger_npc() : CreatureScript("Exchanger_npc") { }

    // 改成静态成员函数
    static std::string GetName(uint32 entry)
    {
        // 建议加个空指针检查,避免无效物品ID导致崩溃
        ItemTemplate const* itemTemp = sObjectMgr->GetItemTemplate(entry);
        return itemTemp ? itemTemp->Name1 : "Unknown Item";
    };

    static bool OnGossipHello(Player* player, Creature* creature) {
        for (uint32 i = 0; i < tokensSize; ++i) {
            std::ostringstream ss;
            ss << "Swap " << Tokens[i].TAKE_AMOUNT << " x " << GetName(Tokens[i].TAKE_ENTRY) << " to " << Tokens[i].GIVE_AMOUNT << " x " << GetName(Tokens[i].GIVE_ENTRY);
            AddGossipItemFor(player, 0, ss.str(), GOSSIP_SENDER_MAIN, i, "Are you sure?", 0, false);
        }
        SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
        return true;
    }

    static bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) {
        player->PlayerTalkClass->ClearMenus();
        if (sender == GOSSIP_SENDER_MAIN && action < tokensSize) {
            if (player->HasItemCount(Tokens[action].TAKE_ENTRY, Tokens[action].TAKE_AMOUNT)) {
                if (player->AddItem(Tokens[action].GIVE_ENTRY, Tokens[action].GIVE_AMOUNT)) {
                    player->DestroyItemCount(Tokens[action].TAKE_ENTRY, Tokens[action].TAKE_AMOUNT, true);
                    player->GetSession()->SendAreaTriggerMessage("%u x %s swapped to %u x %s", Tokens[action].TAKE_AMOUNT, GetName(Tokens[action].TAKE_ENTRY).c_str(), Tokens[action].GIVE_AMOUNT, GetName(Tokens[action].GIVE_ENTRY).c_str());
                }
            } else
                player->GetSession()->SendNotification("You need at least %u x %s", Tokens[action].TAKE_AMOUNT, GetName(Tokens[action].TAKE_ENTRY).c_str());
        }
        OnGossipHello(player, creature);
        return true;
    }

    CreatureAI* GetAI(Creature* creature) const override {
        return new MyAI(creature);
    }

private:
    struct MyAI : public ScriptedAI {
        MyAI(Creature* creature) : ScriptedAI(creature) { }

        bool GossipHello(Player* player) override {
            return Exchanger_npc::OnGossipHello(player, me);
        }

        bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override {
            uint32 sender = player->PlayerTalkClass->GetGossipOptionSender(gossipListId);
            uint32 action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
            return Exchanger_npc::OnGossipSelect(player, me, sender, action);
        }
    };
};

void AddSC_Exchanger_npc() {
    new Exchanger_npc();
}

额外小提示

我在GetName里加了一个空指针检查,避免传入无效的物品ID时触发空指针崩溃——如果sObjectMgr->GetItemTemplate返回nullptr,就返回"Unknown Item",这样程序会更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:19:38