Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当类在某些情况下无法运行时,如何禁用类API?_C++_Class_C++11_Factory - Fatal编程技术网

C++ 当类在某些情况下无法运行时,如何禁用类API?

C++ 当类在某些情况下无法运行时,如何禁用类API?,c++,class,c++11,factory,C++,Class,C++11,Factory,假设我有以下几点: class Processor { public: void Activate(); /* some more interface functions*/ }; void main() { Processor().Activate(); } 类Processor只是提供公共接口的任何类的一个示例 问题 如果类处理器仅在满足某些条件时才可运行,该怎么办。例如,类Processor正在目录X上执行一些文件系统操作,如果目录X不存在,它将无法运行 问题

假设我有以下几点:

class Processor
{
public:
    void Activate();
    /* some more interface functions*/
};

void main()
{
    Processor().Activate();
}
Processor
只是提供公共接口的任何类的一个示例

问题 如果类
处理器
仅在满足某些条件时才可运行,该怎么办。例如,类
Processor
正在目录
X
上执行一些文件系统操作,如果目录
X
不存在,它将无法运行

问题 谁负责验证条件是否满足以及班级是否可运行


让我们将这些条件的计算封装到一个名为
Enabled()

建议1-来电者的责任 在这种情况下,类
处理器的发起者负责在初始化类之前确保满足这些条件

缺点

  • 打电话的人可能不知道情况是什么
  • 这并不能解决更大的问题,如果我们有其他呼叫者没有验证条件呢

  • 建议2——集体责任 在这种情况下,如果未启用类,则禁用所有公共接口函数

    缺点

  • 如果类
    Processor
    具有众多接口功能,那么我们是否检查每个函数开头的
    m_ubissEnabled
    的值
  • 如果将来某个开发人员增强了界面,却忘记检查
    m_bisabled
    的值,该怎么办
  • 如果
    m_bisabled==false

  • 建议3-工厂
    使用处理器\u ptr=shared\u ptr;
    类处理器工厂
    {
    静态处理器\u ptr create()
    {
    处理器ptr p;
    p、 重置(新处理器);
    如果(!p->IsEnabled())
    p、 重置(空PTR);
    返回p;
    }
    };
    类处理器
    {
    公众:
    无效激活();
    bool IsEnabled();
    友邦级处理器厂;
    私人:
    处理器();
    bool m_bis启用;
    };
    
    到目前为止,这个方法是我最喜欢的,因为如果它不能运行,我们会阻止类的生成

    缺点 1.也许是杀伤力过大


    问题: 就最佳实践而言,以下哪项建议更可取?我们还有其他建议吗

    我选择选项3,因为选项2和1很难跟踪,并且强制开发人员在执行每个函数之前始终验证活动标志。此外,您可以通过返回一个空对象来扩展选项#3,该对象实现了接口,但实际上什么也不做。

    我选择选项号#3,因为选项#2和#1很难跟踪,并强制开发人员在每个函数执行之前始终验证活动标志。此外,您可以通过返回一个空对象来扩展选项#3,该对象实现了接口,但实际上什么也不做。

    我也是#3的粉丝,就像igalk一样。但值得一提的是,这是模式的典型情况(资源获取是初始化)。 当构造函数中不满足实例创建的条件时,会引发异常:

    class Processor
    {
    public:    
        Processor()
        {
            //  based on conditions
            if(!folderexist)  // pseudocode
              throw(cannotcreate)
        }
    
    //    void Activate() not needed anymore
    
        /* some more interface functions*/
    private:
    //    bool m_bIsEnabled; not needed anymore
    };
    
    这是libs中已经使用异常的常见模式。我自己也没有什么问题,只要使用得当。不幸的是,我经常看到异常被用作长跳转或保存某些代码行的快捷方式。 失败可以是实例的有效状态。在本例中,IMHO最好创建实例并使用“有效”标志(案例2)。但大多数时候,创建的对象是毫无价值的,失败的信息只是创建者感兴趣的。在这种情况下,RAII可能是更好的选择。如果您不想或不能使用异常,工厂模式将以优雅的方式避免异常。

    我也像igalk一样喜欢#3。但值得一提的是,这是模式的典型情况(资源获取是初始化)。 当构造函数中不满足实例创建的条件时,会引发异常:

    class Processor
    {
    public:    
        Processor()
        {
            //  based on conditions
            if(!folderexist)  // pseudocode
              throw(cannotcreate)
        }
    
    //    void Activate() not needed anymore
    
        /* some more interface functions*/
    private:
    //    bool m_bIsEnabled; not needed anymore
    };
    
    这是libs中已经使用异常的常见模式。我自己也没有什么问题,只要使用得当。不幸的是,我经常看到异常被用作长跳转或保存某些代码行的快捷方式。
    失败可以是实例的有效状态。在本例中,IMHO最好创建实例并使用“有效”标志(案例2)。但大多数时候,创建的对象是毫无价值的,失败的信息只是创建者感兴趣的。在这种情况下,RAII可能是更好的选择。如果您不希望或无法使用异常,工厂模式将以优雅的方式避免异常。

    实际上,根据能够检测到问题的代码,可以使用任何或所有这些策略

    不过,一般来说,我不鼓励在对象中使用“enabled”或“validstate”标志。如果检测到问题,则尽管存在问题,该标志仍有机会继续(例如,忘记检查标志、忘记设置标志、不适当地忽略标志的值)。程序员是人,随着代码变得越来越复杂,犯一个很难追查的错误变得越来越容易

    如果调用方检测到问题,则不应创建该对象,或者(如果该对象已存在)应销毁该对象。然后,它可以向调用者指出问题所在

    如果对象本身检测到问题,那么它应该尽可能地恢复,并向调用者提供指示

    无论哪种方式,这意味着,如果对象存在,它将保持有效状态,直到检测到问题,并且检测到问题将导致对象不存在

    需要给出什么指示取决于问题的严重性,但包括错误代码(调用者可以忽略)和异常(必须忽略)之间的各种方法
    using Processor_ptr = shared_ptr < Processor > ;
    
    class ProcessorFactory
    {
        static Processor_ptr create()
        {
            Processor_ptr p;
    
            p.reset(new Processor);
            if (!p->IsEnabled())
                p.reset(nullptr);
    
            return p;
        }
    };
    
    
    class Processor
    {
    public:
        void Activate();
        bool IsEnabled();
        friend class ProcessorFactory;
    private:
        Processor();
        bool m_bIsEnabled;
    };
    
    class Processor
    {
    public:    
        Processor()
        {
            //  based on conditions
            if(!folderexist)  // pseudocode
              throw(cannotcreate)
        }
    
    //    void Activate() not needed anymore
    
        /* some more interface functions*/
    private:
    //    bool m_bIsEnabled; not needed anymore
    };