创建一个为派生类实现单例的基类

bge*_*ge0 2 c++ inheritance singleton

因此,在你向我开枪告诉我这是一件非常糟糕的事情之前,我只是想表明我想知道这只是为了好奇和可能的代码减少.我想有一个基类来实现派生类的单例.但是,这样做会导致派生类丢失数据.如何根据派生类获取基类来实现单例.例如:

class Application{
public:
/**
 * @brief instance: C++11 [If control enters the declaration concurrently while the     variable is being initialized,
 *the concurrent execution shall wait for completion of the initialization.—§6.7 [stmt.dcl] p4]
 * @return handle to application
 */
static Application& instance(){
    static Application s_Application;
    return s_Application;
}

void setName(std::string Name){
    AppName=Name;
}

std::string getName(){
    return AppName;
}
virtual ~Application(){ }

private:
Application(){}
std::string AppName;
};
Run Code Online (Sandbox Code Playgroud)

现在我创建一个继承自Application的派生类:

class Test:public Application{
    public:
    void printer(std::string test){
        std::cout<<"test\n";
    }
};


int main(int argc, char *argv[]) {
    Application test1=Test::instance();
    //Test test2=static_cast<Test>(test1);
    test1.setName("bla");
    test1.printer(test1.getName());
}
Run Code Online (Sandbox Code Playgroud)

因此,正如预期的那样,test1无法调用.printer()方法,因为返回的对象是"Application"类型.有没有办法将派生类的类型传递回主类并创建派生类的实例?

编辑:我已经使用CRTP传递值,但是当我执行以下操作时它不相等:

Test test1=Test::instance();
Test test2=Test::instance();
cout<<"Is test1 the same as test 2? "<<(&test1==&test2)<<endl;
Run Code Online (Sandbox Code Playgroud)

结果总是假的.

dop*_*ime 5

您还需要将复制构造函数和赋值设置为私有,以便无法复制对象(因为只有对象必须存在).

在你的代码中

Test test1=Test::instance();
Test test2=Test::instance();
Run Code Online (Sandbox Code Playgroud)

你实际上在打电话

Test test1(Test::instance());
Run Code Online (Sandbox Code Playgroud)

这实际上是在呼唤

Test (const Test &);
Run Code Online (Sandbox Code Playgroud)

这是复制构造函数,因此创建了对象的副本.而你实际上是在创建两个不同的对象.这就是地址不同的原因.

因此,将复制构造函数和赋值运算符设为私有,以便没有人可以复制它.

并使用以下内容

Test & test1 = Test::instance();
Test & test2 = Test::instance();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,地址将是相同的.

或者,Test::instance如果需要,可以返回指针.