提供可配置的默认实例 C++中有一个规范模式/最佳实践方法来提供一个类的默认实例,其构造函数需要参数吗?例如,其可用性应如下所示: int main() { //At startup: //Parameterize default instance with some runtime Data Foo::initDefault(getConfigFromFile().getDefaultFooVal()); //1) Use default instance somewhere else in the code: Foo::getDefault().doSomething(); //2) Foo::getDefault().doSomethingElse(); //3) somewhere else in the code, maybe even before the call to initDefault() Foo myFoo(5); myFoo.doSomething(); } void bar(const Foo& foo = Foo::getDefault()) { //... do something with foo } struct Foo { Foo(int i){...}; static Foo& initDefault(int i){ static Foo foo(i); return foo; } static Foo& getDefault() { static Foo& foo = initDefault(-1); return foo; } void doSomething(){...} };

提供可配置的默认实例 C++中有一个规范模式/最佳实践方法来提供一个类的默认实例,其构造函数需要参数吗?例如,其可用性应如下所示: int main() { //At startup: //Parameterize default instance with some runtime Data Foo::initDefault(getConfigFromFile().getDefaultFooVal()); //1) Use default instance somewhere else in the code: Foo::getDefault().doSomething(); //2) Foo::getDefault().doSomethingElse(); //3) somewhere else in the code, maybe even before the call to initDefault() Foo myFoo(5); myFoo.doSomething(); } void bar(const Foo& foo = Foo::getDefault()) { //... do something with foo } struct Foo { Foo(int i){...}; static Foo& initDefault(int i){ static Foo foo(i); return foo; } static Foo& getDefault() { static Foo& foo = initDefault(-1); return foo; } void doSomething(){...} };,c++,C++,注意 1) 2)对同一实例进行操作 如图3所示,Foo不是一个单例 我希望避免提供默认构造函数 我通常的做法如下: int main() { //At startup: //Parameterize default instance with some runtime Data Foo::initDefault(getConfigFromFile().getDefaultFooVal()); //1) Use default instance somewhere

注意

  • 1) 2)对同一实例进行操作
  • 如图3所示,
    Foo
    不是一个单例
  • 我希望避免提供默认构造函数

  • 我通常的做法如下:

    int main() {
        //At startup:
        //Parameterize default instance with some runtime Data
        Foo::initDefault(getConfigFromFile().getDefaultFooVal());
    
        //1) Use default instance somewhere else in the code:
        Foo::getDefault().doSomething();
    
        //2) 
        Foo::getDefault().doSomethingElse();
    
        //3) somewhere else in the code, maybe even before the call to initDefault()
        Foo myFoo(5);
        myFoo.doSomething();
    }
    
    void bar(const Foo& foo = Foo::getDefault()) {
        //... do something with foo
    }
    
    struct Foo {
        Foo(int i){...};
    
        static Foo& initDefault(int i){
            static Foo foo(i);
            return foo;
        }
    
        static Foo& getDefault() {
             static Foo& foo = initDefault(-1);
             return foo;
        }  
    
        void doSomething(){...}
    };
    

    我通常的做法如下:

    int main() {
        //At startup:
        //Parameterize default instance with some runtime Data
        Foo::initDefault(getConfigFromFile().getDefaultFooVal());
    
        //1) Use default instance somewhere else in the code:
        Foo::getDefault().doSomething();
    
        //2) 
        Foo::getDefault().doSomethingElse();
    
        //3) somewhere else in the code, maybe even before the call to initDefault()
        Foo myFoo(5);
        myFoo.doSomething();
    }
    
    void bar(const Foo& foo = Foo::getDefault()) {
        //... do something with foo
    }
    
    struct Foo {
        Foo(int i){...};
    
        static Foo& initDefault(int i){
            static Foo foo(i);
            return foo;
        }
    
        static Foo& getDefault() {
             static Foo& foo = initDefault(-1);
             return foo;
        }  
    
        void doSomething(){...}
    };
    

    如果您确实不想允许使用“默认”实例,我将使用一个指针来指示是否存在singleton实例:

    struct Foo {
        Foo(int i){...};
    
        static Foo& initDefault (int i) {
            static Foo foo(i);
            if (pFoo) {
                throw "Foo's instance is already initialized.";
                // or: foo = Foo(i); if you want to allow re-initialization
            }
            else {
                pFoo = &foo;
            }
            return foo;
        }
    
        static Foo& getDefault() {
             if (!pFoo) {
                 throw "Cannot get Foo's instance before initializing it.";
             }
             return *pFoo;
        }  
    
        void doSomething(){...}
    
    private:
        static Foo *pFoo;
    };
    
    Foo* Foo::pFoo{nullptr};
    

    通过以上内容,您可以使用一种简单的方法来测试实例是否已初始化,而无需动态分配您的单例实例。

    如果您确实不想允许使用“默认”实例,我将使用指针指示单例实例的存在:

    struct Foo {
        Foo(int i){...};
    
        static Foo& initDefault (int i) {
            static Foo foo(i);
            if (pFoo) {
                throw "Foo's instance is already initialized.";
                // or: foo = Foo(i); if you want to allow re-initialization
            }
            else {
                pFoo = &foo;
            }
            return foo;
        }
    
        static Foo& getDefault() {
             if (!pFoo) {
                 throw "Cannot get Foo's instance before initializing it.";
             }
             return *pFoo;
        }  
    
        void doSomething(){...}
    
    private:
        static Foo *pFoo;
    };
    
    Foo* Foo::pFoo{nullptr};
    

    有了以上内容,您就有了一种简单的方法来测试实例是否已初始化,而无需动态分配您的单例实例。

    此实例是否会在整个程序中共享?这是一种单音,扩展为提供另一个实例吗?@HumamHelfawi:是的,这个实例会在整个程序中共享吗?它是一种单音,扩展为提供另一个实例吗?@HumamHelfawi:非常是的,如果您不想允许创建
    initDefault(-1)
    (这就像您显然不想要的默认构造函数),您可以有一个私有静态属性,例如
    pFoo
    初始化为
    nullptr
    static Foo*pFoo=nullptr;
    )然后在
    initDefault
    中将
    pFoo
    设置为
    &Foo
    ,以便在
    getDefault
    中测试
    pFoo
    是否为
    nullptr
    并相应地抛出异常。如果您不想允许创建
    initDefault(-1)
    (这类似于您显然不想要的默认构造函数),您可以有一个私有静态属性,例如,
    pFoo
    初始化为
    nullptr
    static Foo*pFoo=nullptr;
    )然后在
    initDefault
    中将
    pFoo
    设置为
    &foo
    ,这样您就可以在
    getDefault
    中测试
    pFoo
    是否为
    nullptr
    ,并相应地抛出异常。