我正在努力学习单身人士模式,我面临着设计困境。
工作单身如下: 注意静态myClass * mc;公开,就像public static myClass * getInstance
一样1)working_code
#include "iostream"
using namespace std;
class myClass {
private:
myClass() {
}
void operator = (const myClass &);
myClass (const myClass & );
public:
static myClass * mc;
static myClass * getInstance () {
cout << "\n getInstance callsed \n";
if (mc == NULL) {
mc = new myClass();
}
return mc;
}
void print() {
cout <<"\n call to print donem \n";
}
};
myClass * myClass::mc =NULL;
int main() {
myClass * mc = myClass::getInstance ();
mc->print();
return 0;
}
2)NOT_WORKING_CODE
不工作的实例会产生编译错误。请注意,我尝试将static myClass * mc;
保密为私有
#include "iostream"
using namespace std;
class myClass {
private:
static myClass * mc;
myClass() {
}
void operator = (const myClass &);
myClass (const myClass & );
public:
static myClass * getInstance () {
cout << "\n getInstance callsed \n";
if (mc == NULL) {
mc = new myClass();
}
return mc;
}
void print() {
cout <<"\n call to print donem \n";
}
};
int main() {
myClass * mc = myClass::getInstance ();
mc->print();
return 0;
}
输出:
在函数main':
undefined reference to
myClass :: mc'中
未定义的引用`myClass :: mc'
问题:
1)为什么我收到上述NOT_WORKING_CODE
的错误2)我认为使用public myClass :: mc是违反设计规则的,因为我们应该只将接口设为public。我面临的问题是上面的工作代码1)的用户可以直接访问myClass :: mc来调用一些函数,比如print myClass :: mc-&gt; print();没有先调用实例..
即当我在上面的1)中更改了以下内容时
int main() {
myClass::mc->print();
myClass * mc = myClass::getInstance ();
mc->print();
return 0;
}
我打印时感到恐惧
call to print donem
getInstance callsed
call to print donem
即,我可以在没有有效实例的情况下调用,因为该实例是在getInstance
中创建的。这意味着如果print正在访问某些指针等,我可能会遇到一些异常。
这因此表明1)具有设计缺陷。如何纠正同样的问题......
答案 0 :(得分:2)
//myClass * myClass::mc =NULL;
出现错误是因为您注释掉了该行,而不是因为您将变量设为私有。因此,为了使代码与变量private一起工作,只是不要对该行进行注释,它将进行编译。
见这里:What is an undefined reference/unresolved external symbol error and how do I fix it?
但是你不应该这样使用单身模式。事实上,尽量避免使用单身,如果你真的必须使用它们,请使用Meyers Singleton(google for it!)
答案 1 :(得分:1)
mc
是一个静态数据成员,因此必须像在第一种情况下那样明确初始化。
myClass * myClass::mc =NULL;
你错过了第二种情况。
请参阅此链接http://www.parashift.com/c++-faq/link-errs-static-data-mems.html
BTW,这是链接器错误而不是编译器错误。