2009-09-03 11 views
0

Как я могу вызвать функцию и оставить свой конструктор закрытым? Если я создаю класс static, мне нужно объявить имя объекта, которое компилятор использует для вызова конструктора, чего не может, если конструктор является закрытым (также объект будет посторонним). Вот код, который я пытаюсь использовать (это не компилируется):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

Выясните, к какой цели вы относитесь? Похоже, вы пытаетесь сохранить список всех экземпляров Referral. Почему вы хотите, чтобы ваш конструктор был закрыт? –

ответ

2

Основываясь на вашем main код, который я думаю, что вы снимаете для является одноточечно, который будет выглядеть примерно так:

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

Я не стреляю в синглтон, хотя вижу, где вы это думали. Это была очень и очень упрощенная версия нескольких случаев проверок, которые я позже буду реализовывать. спасибо, хотя, я все равно буду видеть, могу ли я использовать этот тип реализации, для этого или иначе. –

+0

Идея по-прежнему будет прежней - переименуйте 'instance()' в 'createInstance()' и реализуйте ее, чтобы каждый раз возвращать новый экземпляр объекта. Конструктор по-прежнему закрыт. –

+0

Какова польза от использования экземпляра(). Представьте, что реализация Chickencha лишена его? –

6

Что случилось с наличием частного конструктора и статическим методом фабрики?

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

Во-первых, вам нужно сделать Submit статический функция. Тогда вы можете просто сказать

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

не создавая экземпляр Referral.

Затем в вашей функции отправки вы создаете временный объект Referral, который исчезает почти сразу. Вероятно, вы хотите создать экземпляр динамически с новым. В зависимости от того, как вы хотите управлять этим, вы можете переместить код, нажав на список в Submit.

Наконец, я бы сделал ваш список экземпляров Referral статической переменной-членом, а не тем, как у вас есть это сейчас.

(Также, передавая эти строки аргументы по ссылке, вероятно, будет хорошей идеей.)

+0

Можете ли вы объяснить преимущество прохождения по ссылке? –

+0

Передача по значению (это то, что вы делаете сейчас) создает копию объекта. Поэтому каждый раз, когда вы вызываете одну из этих функций, конструктор экземпляра строки получает ненужное обращение. Поскольку вы не изменяете переданную строку, вы можете передать ее по ссылке и сделать ее постоянной и избегать этих вызовов конструктора копирования. Как правило, хорошая практика передавать все, что не является примитивным типом (int, float, char и т. Д.) По ссылке и сделать его const, если это возможно. –

+0

@Chickecha: когда объект Referral добавляет себя в список, он создает копию, поэтому, пока метод создает только временный объект, в списке есть новый объект с содержимым временного. –

1

В то время как весь код имеет некоторый запах вокруг, вы можете заставить его работать только путем незначительных изменений, которые не имеют никакого отношения к ваш вопрос.

Чтобы скомпилировать его, я удалил регулярное выражение (я не использую компилятор с поддержкой C++ 0x) и 'using namespace tr1'. Переместите реализацию конструктора после определения глобального объекта Referral. Изменить . для :: в основной функции, когда вы ссылаетесь на статический метод.

// 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() создавал бы объект, а затем включить его в список ...

Я думаю, вам может быть полезно выразить то, что вы намерены делать, многие люди здесь помогут вам с выбором дизайна и причинами для них.