0

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

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

#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

4 回答 4

6

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

class Example {
  Example() { ... }
public:
  static Example CreateExample() {
    return Example();
  }
};
于 2009-09-03T20:53:15.503 回答
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));
}
于 2009-09-03T21:02:47.197 回答
1

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

为了使其编译,我删除了正则表达式包含(我没有使用支持 C++0x 的编译器)和“使用命名空间 tr1”。将构造函数实现移到引用全局对象的定义之后。更改 . 当您引用静态方法时,主要功能中的 :: 。

// 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 类中的方法可能会破坏内容)。将所有属性设为私有,并仅提供用户代码所需功能的访问器(在大多数情况下,只读访问就足够了)。在构造函数中使用初始化列表,并按照它们在类定义中出现的相同顺序初始化那里的所有成员。

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

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

于 2009-09-03T21:42:47.413 回答
1

首先,您需要将 Submit 设为静态函数。然后你可以说

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

无需创建引用实例。

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

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

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

于 2009-09-03T21:08:16.873 回答