2009-09-03 110 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()方法创建它会更有意义该对象,然后将其包括在列表中...

我想你可能会从表达你打算做的事情中受益,这里的许多人将帮助你们设计选择和理由。