1

我正在尝试学习单例模式,但我面临着设计困境。

一个工作单例如下所示:注意 static myClass * mc; 公开,就像 public static myClass * getInstance

1) 工作代码

#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 tomyClass::mc' 中未定义对 `myClass::mc' 的引用

问题 :

1) 为什么我收到上述 NOT_WORKING_CODE 的错误

2)我认为使用 public myClass::mc 是违反设计规则的,因为我们应该只将接口设为 public 。这里我面临的问题是上面工作代码1)的用户可以直接访问myClass::mc来调用一些函数,比如print myClass::mc->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) 存在设计缺陷。如何纠正同样的问题是......

4

2 回答 2

2

//myClass * myClass::mc =NULL; 出现错误是因为您注释掉了该行,而不是因为您将变量设为私有。因此,要使代码与私有变量一起工作,只需不要注释掉该行,它就会编译。

请参阅此处:什么是未定义的引用/未解决的外部符号错误,我该如何解决?

但是你不应该以这种方式使用单例模式。事实上,尽量避免使用单例,如果你真的必须使用它们,请使用 Meyers Singleton(google for it!)

于 2013-05-27T06:46:21.313 回答
1

mc是一个静态数据成员,因此它必须像您在第一种情况下所做的那样显式初始化。

myClass * myClass::mc =NULL;

在第二种情况下,您错过了这样做。

请参阅此链接http://www.parashift.com/c++-faq/link-errs-static-data-mems.html

顺便说一句,这是链接器错误而不是编译器错误。

于 2013-05-27T06:59:03.257 回答