C ++私有构造的类

时间:2009-09-03 20:49:32

标签: c++ class static constructor private

如何调用函数并保持构造函数的私有性?如果我使类静态,我需要声明一个编译器用来调用构造函数的对象名,如果构造函数是私有的,它也不能(对象也是无关的)。以下是我尝试使用的代码(可编译):

我想保持构造函数是私有的,因为我稍后会在添加对象之前进行大量检查,在所有提交的变量不是唯一的时候修改以前的对象而不是创建新对象。

#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);
}

4 个答案:

答案 0 :(得分:6)

拥有私有构造函数和静态工厂方法有什么问题?

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

答案 1 :(得分:2)

根据您的main代码,我认为您拍摄的内容是 singleton ,它看起来像是:

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);
}

另一种可能性是,您希望保留一份推荐列表,在这种情况下,您可以使用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));
}

答案 2 :(得分:1)

首先,您需要提交一个静态函数。然后你可以说

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

不创建推荐实例。

然后,在您的提交功能中,您只创建一个几乎立即消失的临时Referral对象。您可能想要做的是使用new动态创建一个实例。根据您希望如何管理它,您可能希望将推送到列表的代码移动到提交。

最后,我会将您的引荐实例列表设为静态成员变量,而不是现在的方式。

(另外,通过引用传递这些字符串参数可能是个好主意。)

答案 3 :(得分:1)

虽然整个代码都有一些嗅觉,但只需进行与您的问题无关的轻微更改,即可使其正常工作。

为了使它编译,我删除了正则表达式include(我没有使用支持C ++ 0x的编译器)和'using namespace tr1'。在引用全局对象的定义之后移动构造函数实现。改变。当你引用静态方法时,在main函数中使用::。

// 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);
}

现在,从设计的角度来看,代码有一种恶臭。如果确实想要添加Referral对象的全局列表,请考虑将其作为Referral类的私有静态属性,以便您可以对其进行更多控制(只有Referral类中的方法可能会破坏内容)。将所有属性设为私有,并仅提供用户代码所需功能的访问者(在大多数情况下,只读访问就足够了)。在构造函数中使用初始化列表,并按照它们在类定义中出现的顺序初始化所有成员。

所有修复后,它仍然有一些气味。 static函数创建了一个类的实例,但是构造函数是在map中包含自身的那个(??)如果构造函数没有与map交互,那将会更有意义,并且submit()方法会创建该对象,然后将其包含在列表中......

我认为你可能会从表达你打算做的事情中受益,很多人会帮助你们设计选择和理由。