2009-09-03 112 views
0

我該如何調用一個函數並讓我的構造函數保持私有?如果我讓這個類是靜態的,我需要聲明一個編譯器用來調用構造函數的對象名稱,如果構造函數是私有的(對象也是無關的),那麼它不能。這裏是我嘗試使用的代碼(這是編譯):C++私人構造類

我想保持構造私有,因爲我會在後面添加一個對象之前是做了很多檢查,修改先前的對象時,所有提交變量不是唯一的,而是創建新的對象。

#include <iostream> 
#include <fstream> 
#include <regex> 
#include <string> 
#include <list> 
#include <map> 

using namespace std; 
using namespace tr1; 

class Referral 
{ 
public: 
    string url; 
    map<string, int> keywords; 

    static bool submit(string url, string keyword, int occurrences) 
    { 
     //if(Referrals.all.size == 0){ 
     // Referral(url, keyword, occurrences); 
     //} 
    } 

private: 
    list<string> urls; 

    Referral(string url, string keyword, int occurrences) 
    { 
     url = url; 
     keywords[keyword] = occurrences; 
     Referrals.all.push_back(this); 
    } 
}; 

struct All 
{ 
    list<Referral> all; 
}Referrals; 

int main() 
{ 
    Referral.submit("url", "keyword", 1); 
} 
+0

你能更清楚你的目標是什麼嗎?它看起來像你試圖保留引薦的所有實例的列表。爲什麼你想讓你的構造函數保持私有? – 2009-09-03 21:00:56

回答

2

我想你拍攝的是一個,這看起來是這樣的:

class Referral 
{ 
private: 
    Referral() 
    { 
     //... 
    } 

public: 
    static Referral& instance() 
    { 
     static Referral instance_s; 
     return instance_s; 
    } 

    bool submit(string url, string keyword, int occurrences) 
    { 
     //... 
    } 
}; 

然後你在main通話將如下所示:

int main() 
{ 
    Referral::instance().submit("url", "keyword", 1); 
} 

另一種可能性是您希望保留推薦人列表,在這種情況下您c一個使用struct和它們的列表來完成你在找什麼:

struct Referral 
{ 
    Referral(string url, string keyword, int occurrences) : 
     url_m(url), keyword_m(keyword), occurrences_m(occurrences) 
    { } 

    string url_m; 
    string keyword_m; 
    int occurrences_m; 
}; 

typedef std::vector<Referral> ReferralSet; 

然後你在main通話將如下所示:

int main() 
{ 
    ReferralSet set; 

    set.push_back(Referral("url", "keyword", 1)); 
} 
+0

我不是爲一個單身人士拍攝的,雖然我看到你在想什麼。這只是我將在稍後實施的多個檢查案例的非常非常簡化的版本。不過謝謝,我仍然會看到我是否可以使用這種類型的實現。 – 2009-09-03 21:05:54

+0

這個想法仍然是一樣的 - 將'instance()'重命名爲'createInstance()',並實現它以每次都返回一個新的對象實例。構造函數仍然是私有的。 – 2009-09-03 21:08:06

+0

使用實例()的好處是什麼?通過Chickencha的實現提交,忽略它? – 2009-09-03 21:12:42

6

擁有私有構造函數和靜態工廠方法有什麼問題?根據您main代碼

class Example { 
    Example() { ... } 
public: 
    static Example CreateExample() { 
    return Example(); 
    } 
}; 
1

首先,您需要提交一個靜態功能。那麼你可以只說

Referral::Submit(url, keyword, occurrences); 

而不創建引用實例。

然後,在您的提交功能中,您只創建一個幾乎立即消失的臨時引用對象。可能你想要做的是用new動態創建一個實例。根據您想要管理的方式,您可能需要將推送到列表中的代碼移入提交。

最後,我會讓你的列表引用實例成爲一個靜態成員變量,而不是你現在擁有它。

(另外,通過引用傳遞的字符串參數可能會是一個好主意。)

+0

你能否解釋通過引用傳遞的好處? – 2009-09-03 21:10:02

+0

按值傳遞(這是您現在正在做的)創建對象的副本。所以每次調用其中一個函數時,都會不必要地調用字符串的複製構造函數。由於你沒有修改傳入的字符串,你可以通過引用傳遞它,並使其成爲常量並避免這些複製構造函數調用。一般來說,好的做法是通過引用來傳遞不是基本類型的東西(int,float,char等),並且如果可能的話將其設置爲const。 – 2009-09-03 21:13:05

+0

@Chickecha:當引用對象將自己添加到正在創建副本的列表中時,所以雖然該方法只創建一個臨時對象,但列表中還有一個新對象,其中包含臨時對象的內容。 – 2009-09-03 21:44:33

1

雖然整個代碼有一些氣味身邊,你可以把它只是使那些無關的細微變化工作你的問題。

爲了讓它編譯,我刪除了正則表達式include(我沒有使用帶有C++ 0x支持的編譯器)和'using namespace tr1'。在引用全局對象的定義之後移動構造函數實現。改變。當你引用一個靜態方法時,用於主函數中的a ::。

// changes... 
//#include <regex> 
... 
//using namespace tr1; 
... 
class Referral { 
... 
    Referral(string url, string keyword, int occurrences); // added ; moved the implementation bellow the Referrals variable definition 
... 
struct All { 
... 
} Referrals; 

// added constructor implementation here (Referrals global must be defined before use): 
Referral::Referral(string url, string keyword, int occurrences) 
{ 
    url = url; 
    keywords[keyword] = occurrences; 
    Referrals.all.push_back(*this); // added dereference, this is of type Referral*, not Referral 
} 

int main() 
{ 
    Referral::submit("url","keyword",1); 
} 

現在,從設計的角度來看,代碼有惡臭。如果真的想要在全局列表中添加引用對象,請考慮將其設置爲引用類的私有靜態屬性,以便您可以對其進行更多的控制(只有引用類中的方法可能會破壞內容)。使所有屬性保持私有狀態,並只提供用戶代碼所需功能的訪問者(大多數情況下,只讀訪問權限就足夠了)。在構造函數中使用初始化列表,並按照它們出現在類定義中的順序初始化所有成員。

儘管如此,它仍然有一些氣味。靜態函數創建類的一個實例,但構造函數是包含在地圖中的構造函數(??)如果構造函數不與地圖交互,並且submit()方法創建它會更有意義該對象,然後將其包括在列表中...

我想你可能會從表達你打算做的事情中受益,這裏的許多人將幫助你們設計選擇和理由。