【问题标题】:How can a class know who called its method?一个类如何知道谁调用了它的方法?
【发布时间】:2014-01-19 15:25:34
【问题描述】:

目前我为每个使用它的代码创建一个新的类实例。构造函数采用字符串名称,所以我知道在类内部,谁调用了我的方法。

class Log {
public:
    Log(std::string Name) : name(Name) {}
    void Print(std::string Message) {
        std::cout << name << " said " << Message << std::endl;
    }
private:
    std::string name;
};

这个示例类被一系列模块使用,这些模块派生自抽象类型。

class Module {
public:
    Module(std::string Name) : log(new Log(Name)) {}
    virtual void Update() = 0;
private:
    Log *log;
};

class Renderer : public Module {
public:
    void Update() {
        log->Print("Hello World!");
    }
};

Renderer renderer("Renderer");
renderer.Update(); // "Renderer says Hello World!"

但现在,我想为所有模块共享同一个 Log 实例。我怎样才能做到这一点,并且仍然与方法调用的来源不同?

背景:有很多模块,它们使用两种类型的类。首先,在模块之间全局共享的管理器。其次,像上面的示例类这样的助手是为每个模块单独创建的。但我想找到两者的单一抽象来实现更简单的设计。考虑一个日志助手,它应该用不同的、均匀分布的颜色为不同模块的消息着色。这样的助手需要在所有模块之间共享状态。

【问题讨论】:

  • 这不是一个好主意,但你可以试试这个:gnu.org/software/libc/manual/html_node/Backtraces.html
  • 你不能。出于这个原因,我们使用访问修饰符。
  • 模块不能告诉记录器它们是哪个模块吗?或者如果只是颜色发生变化,使用哪种颜色?
  • @TomaszKłak 我不是指某种反射或回溯,而是在 C++ 中解决我的问题的设计。
  • @JosephMansfield 他们可以。像log-&gt;Print(name, "Hello World!"); 这样的东西。但我正在寻找一种方法将该逻辑放入基础 Module 类或 Log 类中。

标签: c++ methods global state


【解决方案1】:

您可以通过对Log 类进行一些更改来简化该过程,以使其改为调用全局日志函数。这减少或消除了对当前使用日志记录方式的大量更改。

class Log {
public:
    explicit Log(const std::string& name) : name(name) {}
    void Print(const std::string& message) const {
        GlobalLogPrint(name, message);
    }

private:
    const std::string name;
};

您可以继续动态分配Log 对象的实例,也可以使用组合。

class Module {
public:
    explicit Module(const std::string& name) : log(name) {}
    virtual void Update() = 0;
protected:
    Log log;
};

class Renderer : public Module {
public:
    void Update() {
        log.Print("Hello World!");
    }
};

【讨论】:

  • 是否可以将Log类嵌入到全局on中?
  • 仅当您将Log 类更改为不调用全局类时,否则您最终会出现循环依赖。
【解决方案2】:

我想我明白你想要什么。试试这个:

class Module
{
public:
    Module(std::string name) : name(name) {}
    void Update()
    {
        VUpdate(name);
    }

private:
    virtual void VUpdate(const std::string &name) = 0;

protected:
    static Log *log;

private:
    std::string name;
};

class Renderer : public Module
{
private:
    virtual void VUpdate(const std::string &name)
    {
        log->Print(name, "Hello World!");
    }
};

Log *Module::log = new Log();

您的记录器必须更改以在其Print 成员中接受调用者的姓名。

【讨论】:

  • 你认为有没有一种方法可以不用每次都明确传递name
  • 并非如此。如果您希望所有潜在调用者共享Log 实例,那么它必须是可变的。 不知何故Log 必须被告知是谁在打电话。
  • 我可能会从 Module 类中删除 name,而只使用宏。
猜你喜欢
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 2020-05-05
  • 1970-01-01
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多