所以,在你向我开枪告诉我这是一件非常糟糕的事情之前,我只是想表明我想知道这只是为了好奇和可能的代码减少。我想有一个基类来实现派生类的单例。但是,这样做会导致派生类丢失数据。如何根据派生类获取基类来实现单例。例如:
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;
};
现在我创建一个继承自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());
}
正如预期的那样,test1无法调用.printer()方法,因为返回的对象是“Application”类型。有没有办法将派生类的类型传递回主类并创建派生类的实例?
编辑:我已经使用CRTP传递了值,但是当我执行以下操作时它并不相同:
Test test1=Test::instance();
Test test2=Test::instance();
cout<<"Is test1 the same as test 2? "<<(&test1==&test2)<<endl;
结果总是 FALSE 。
答案 0 :(得分:5)
您还需要将复制构造函数和赋值设置为私有,以便无法复制对象(因为只有对象必须存在)。
在您的代码中
Test test1=Test::instance();
Test test2=Test::instance();
你实际上是在打电话
Test test1(Test::instance());
实际上正在调用
Test (const Test &);
这是复制构造函数,因此创建了对象的副本。而你实际上是在创建两个不同的对象。这就是地址不同的原因。
因此,将复制构造函数和赋值运算符设为私有,以便没有人可以复制它。
并使用以下
Test & test1 = Test::instance();
Test & test2 = Test::instance();
在这种情况下,地址将相同。
或者,如果需要,您可以在Test::instance
中返回指针。