首页 > 解决方案 > 我正在尝试在 C++ 中创建一个日志记录框架,但信息没有传递给记录器的子组件,我做错了什么?

问题描述

这是我的代码,当我尝试运行它时,main 会输出放置在 LoggerComponent 中的信息,而不是 Logger 本身。我不知道为什么,是什么阻止了记录器将信息传递到底层记录器组件?

我尝试使用来自http://www.cplusplus.com/reference/map/map/https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl的信息/

记录器.cpp:

#include "logger.hpp"

Logger::Logger(bool verbose, bool fileoutput)
{
    if(verbose)
    {
        LoggerComponent c1(LoggerLevel::DEBUG, &std::cout);
        addLogger (LoggerType::CONSOLE, &c1);
        c1.output (LoggerLevel::DEBUG, "This is the start of console output");
    }
    if(fileoutput)
    {

    }
}

void Logger::output(LoggerLevel level, std::string message)
{
    for(auto& x : components)
    {
        x.second->output (level, message);
    }
}

void Logger::addLogger(LoggerType type, LoggerComponent* component)
{
    if(components.find (type) == components.end ())
        components.emplace(type, component);
}

LoggerComponent* Logger::getLogger (LoggerType type)
{
    if(components.find (type) != components.end ())
        return components.at (type);
    return nullptr;
}

void Logger::clearLoggers()
{
    components.clear ();
}

void Logger::removeLogger(LoggerType type)
{
    if(components.find (type) != components.end ())
        components.erase (type);
}

记录器.hpp

#ifndef LOGGER_HPP
#define LOGGER_HPP

#include "loggercomponent.hpp"

#include <map>

enum class LoggerType
{
    CONSOLE,
    FILE
};

class Logger
{
public:
    explicit Logger(bool verbose, bool fileoutput);

    void output(LoggerLevel level, std::string message);

    void addLogger(LoggerType type, LoggerComponent* component);
    void removeLogger(LoggerType type);
    void clearLoggers();
    LoggerComponent* getLogger(LoggerType type);

private:
    std::map<LoggerType, LoggerComponent*> components;
};

#endif // LOGGER_HPP

主文件

#include "logger.hpp"

int main()
{
    int* p;
    int i = 5;
    int j = 5;
    p = &i;
    std::cout << p << std::endl;
    p = &j;
    std::cout << p << std::endl;

    LoggerComponent c(LoggerLevel::DEBUG, &std::cout);

    c.output (LoggerLevel::INFO, "Hello World!");
    c.output (LoggerLevel::CRITICAL, "Hello World!");

    Logger c2(true, true);

    std::cout << c.getOutputStream () << std::endl;
    std::cout << c2.getLogger (LoggerType::CONSOLE)->getOutputStream () << std::endl;

    c2.output (LoggerLevel::INFO, "Hello World!");
    c2.output (LoggerLevel::CRITICAL, "Hello World!");
}

记录器组件.hpp

#ifndef LOGGERCOMPONENT_HPP
#define LOGGERCOMPONENT_HPP

#include <iostream>
#include <string>
#include <ctime>

enum class LoggerLevel
{
    INFO,
    DEBUG,
    WARNING,
    ERROR,
    CRITICAL
};

class LoggerComponent
{
public:
    explicit LoggerComponent(LoggerLevel level, std::ostream* output);

    LoggerLevel getMinimumLevel();
    std::ostream* getOutputStream();
    void setMinimumLevel(LoggerLevel level);
    void setOutputStream(std::ostream* output);

    void output(LoggerLevel level, std::string outputMessage);

private:
    std::string getLevelString(LoggerLevel level);

    LoggerLevel minimumLevel;
    std::ostream* outputStream;
};

#endif // LOGGERCOMPONENT_HPP

记录器组件.cpp

#include "loggercomponent.hpp"

LoggerComponent::LoggerComponent(LoggerLevel level,
                                 std::ostream* output)
{
    setMinimumLevel (level);
    setOutputStream (output);
}

void LoggerComponent::setMinimumLevel(LoggerLevel level)
{
    if(minimumLevel != level)
        minimumLevel = level;
}

void LoggerComponent::setOutputStream(std::ostream *output)
{
    if(outputStream != output)
        outputStream = output;
}

LoggerLevel LoggerComponent::getMinimumLevel()
{
    return minimumLevel;
}

std::ostream* LoggerComponent::getOutputStream()
{
    return outputStream;
}

std::string LoggerComponent::getLevelString(LoggerLevel level)
{
    switch (level) {
    case LoggerLevel::INFO:
        return "INFO";
    case LoggerLevel::DEBUG:
        return "DEBUG";
    case LoggerLevel::WARNING:
        return "WARNING";
    case LoggerLevel::ERROR:
        return "ERROR";
    case LoggerLevel::CRITICAL:
        return "CRITICAL";
    }
    return nullptr;
}

void LoggerComponent::output(LoggerLevel level, std::string outputMessage)
{
    if(level >= minimumLevel)
    {
        time_t now = time(nullptr);
        *outputStream << ctime(&now)
                      << (getLevelString (level) + " >> " + outputMessage)
                      << std::endl << std::endl;
    }
}

输出:

0x60fda8 0x60fdac 2019 年 10 月 1 日星期二 12:29:14 关键 >> Hello World!

Tue Oct 01 12:29:14 2019 DEBUG >> 这是控制台输出的开始

0x6fd0cd00 0x60fdb0

标签: c++c++11loggingmingw-w64

解决方案


您正在将一个指向构造函数 ( c1) 本地对象的指针存储在components. 当您稍后尝试使用它时,它将被破坏并且指针无效。

将对象本身(或者std::unique_ptr,如果您有充分的理由不存储对象本身,则将其存储在地图中)。


推荐阅读