【问题标题】:How can I prevent other coders from bypassing my wrapper function?如何防止其他编码人员绕过我的包装函数?
【发布时间】:2014-12-28 04:36:14
【问题描述】:

我有一个处理日志的 C++ 类 (ClassLog),我在自己的类 (ClassWork) 中实现了这个类的一个实例。因为我的 ClassWork 日志中需要时间戳,所以我添加了一个包装函数,在将要写入 ClassLog 的字符发送之前,将当前时间添加到每个新行。

这意味着在 ClassWork 中添加新日志输出的任何人都必须使用我的包装函数,否则日志将被弄乱(缺少时间戳)。但是,ClassLog 有一个公共成员函数,它允许任何人绕过我的包装函数,直接写入日志。我可以做些什么来在 ClassWork 中有一个 ClassLog 的实例,但阻止 ClassWork 访问 ClassLog 公共成员函数,除非它们是从我的包装函数访问的?这将使其他编码员不可能意外地搞砸日志。

【问题讨论】:

  • 允许您绕过包装器的功能真的必须公开吗?
  • 不幸的是,我对 ClassLog 没有权限,因为它是一个很久以前开发的类,并且在我的团队使用的代码中随处使用。因此,任何人都可以使用我的 ClassWork 中声明的 ClassLog 实例进行编写。 ClassLog 本身的实例是私有的,但我担心人们直接使用 ClassLog 打印而不是我的包装器将代码添加到 ClassWork。

标签: c++ class oop wrapper


【解决方案1】:

我能想到的选项:

  1. 不要将ClassLog 公开为一个类。使其成为ClassWork 的实现细节。

  2. ClassLog的相关成员函数设为私有。声明ClassWorkClassLog的朋友。

  3. 将时间戳作为ClassLog的成员函数中的必需参数。

  4. 使时间戳成为ClassLog 的成员函数中的可选参数。如果未提供,则使用当前时间计算时间戳并将其添加到日志中。

【讨论】:

    【解决方案2】:

    您可以声明您的包装函数const,并将保存字符串的变量设置为可变的,以便 const 函数仍然可以修改它。

    class ClassLog {
    
        mutable std::string log;
    
        public: 
        const std::string writeToLog(std::string logToWrite) const 
        {
            log = logToWrite;
            return log;
        };
    }
    
    class classWork {
    
        ClassLog logs;
    
        public: 
        const void wrapper();
    }
    

    【讨论】:

    • 它将允许 ClassWork 仅访问 ClassLog 的私有和受保护成员。我会用我认为可能有帮助的更多信息来更新我的答案。
    • A const void 返回类型?
    • 是的,那是错误的。随意编辑我的代码。我只是想证明一个观点。
    【解决方案3】:

    ClassLog的日志记录方式是虚拟的吗?如果是这样,请制作您自己的、专门的 ClassLog 实现;我们称它为 ClassWorkLog。在您的 ClassWork 中使用它而不是 ClassLog。例如:

    class ClassLog {
    public:
        virtual void writeToLog(std::string message) { ... }
        ...
    };
    
    // Implement wrapper class
    class ClassWorkLog : ClassLog {
    public:
        virtual void writeToLog(std::string message) override {
            std::string timestamp = getTimeStamp();
            ClassLog::writeToLog(timestamp + message);
        }
    };
    

    如果它不可扩展,您可以使用组合代替,您的包装类包含一个 ClassLog:

    // Implement wrapper class
    class ClassWorkLog {
    public:
        void writeToLog(std::string message) {
            std::string timestamp = getTimeStamp();
            classLog.writeToLog(timestamp + message);
        }
    
    private:
        ClassLog classLog;
    };
    

    现在,在 ClassWork 中,使用您的 ClassWorkLog 包装类而不是标准 ClassLog。

    class ClassWork {
    public:
        void doStuff() {
            ...
            workLog.writeToLog("test");
        }
    
    private:
        ClassWorkLog workLog;
    };
    

    【讨论】:

      【解决方案4】:

      从 ClassLog 派生您自己的日志记录类并存储该实例(或通过构造函数注入)。然后用您自己的覆盖公共日志记录功能。理想情况下,日志记录方法应该是虚拟的。

      #include <iostream>
      #include <stdio.h>
      #include <time.h>
      #include <string>
      
      using namespace std;
      
      class ClassLog
      {
          public:
          void Log(string message)
          {
              std::cout << message << std::endl;
          }
      };
      
      class DerivedClassLog : public ClassLog
      {
      
          private:
          const std::string currentDateTime() 
          {
              time_t     now = time(0);
              struct tm  tstruct;
              char       buf[80];
              tstruct = *localtime(&now);
              strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);
      
              return buf;
          }
      
          public:
          void Log(string message)
          {
              ClassLog::Log(currentDateTime() + " " + message);
          }
      };
      
      int main()
      {
         DerivedClassLog logger;
      
         logger.Log("Hello");
      
         return 0;
      }
      

      【讨论】:

        【解决方案5】:

        我不会像其他答案所暗示的那样继承和专攻。相反,我会使用 ClassLog 成员是私有的包装类。

        class TimestampedLog
        {
        public:
            write(std::string msg) {
                log.write(getCurrentTime());
                log.write(msg);
            }
        private:
            ClassLog log;
        };
        
        class ClassWork
        {
        public:
            void doSomething() {
                // ...
                log.write("Did something");
            }
        private:
            TimestampedLog log;
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-08
          • 2010-10-02
          • 1970-01-01
          • 2019-10-29
          • 2020-05-24
          • 2023-03-24
          相关资源
          最近更新 更多