2011-01-12 4 views
1

Это сводило меня с ума. Я получал сообщение «Нет соответствия функции« Ошибка WordCloud :: WordCloud() ». Кажется, что был вызван конструктор по умолчанию, но поскольку я не определял его, возникла ошибка.C++ - почему этот член должен быть объявлен статическим?

Конструктор:

WordCloud(map<string, int> *source); 

И в главном файле CPP, ошибка происходила на указанной линии

class FontTestingApp : public AppBasic 
{          // <-- error was appearing on this line 
public: 
    void setup(); 
    void mouseDown(MouseEvent event); 
    void update(); 
    void draw(); 

    map<string, int> wordList; 
    WordCloud wc;  // comment out this line and it compiles 
}; 

Итак, я предполагаю, что объект Wordcloud был быть инстанцирован когда был создан экземпляр класса FontTestingApp.

Если я закомментируйте строку

WordCloud wc; 

Затем он компилирует.

Чтобы исправить это, я, наконец, изменил строку

static WordCloud wc; 

И скомпилированного.

Я действительно не знаю, почему, и это не очень хорошо :) Если бы кто-нибудь мог объяснить, что здесь происходит, я был бы очень благодарен. Я использую libCinder кстати (libcinder.org)

+0

Это декларация ctor, вы пробовали реализовать пустой ctor? – mingos

+0

После добавления статики все еще работает, если вы создаете объект 'FontTestingApp' в вашем' main'? – Jaywalker

+0

Нет, если я стану статичным, он будет компилироваться, но не будет связываться. Как отмечали другие, статические просто маскируют проблему. Проблема была более элементарной; Я должен был объявить wc как WordCloud * - WordCloud * wc. При объявлении как wc я создавал экземпляр, и, таким образом, вызывал конструктор по умолчанию. Заставляет меня чувствовать себя довольно глупо :) Я виню слишком много лет в Java ... – Sam

ответ

1

Поскольку вы предоставили пользовательский конструктор (для WordCloud), компилятор больше не генерирует значение по умолчанию ctor.

Если ваш WordCloud не ваш класс, вы убедитесь, что во всех ваших конструкторах (в том числе по умолчанию для класса FontTestingApp) вы правильно создаете элемент в списке инициализаторов.

+0

Пользовательские конструкторы не являются частью правила 3. –

+0

@ Oli, я знаю, может быть, я должен отредактировать свои ans, чтобы добавить «Следуйте правилу из трех, если вам удастся определить ваши собственные конструкторы», я отвлекся на поиск ссылки .. – Nim

+0

Я так не думаю ; правило-3 является полностью отдельной проблемой. –

1

Ваша догадка о том, почему компилятор искал конструктор по умолчанию, верен; вы явно не вызываете соответствующий конструктор WordCloud в списке инициализаторов в конструкторе FontTestingApp.

Что касается того, почему подход static «работает»; это не так. Декларации статических членов также должны сопровождаться определениями (обычно в строках WordCloud FontTestingApp::wc(/*args*/); в файле CPP где-то. Без этого не создается экземпляр объекта и, следовательно, никакого конструктора не вызывается.

Примечание: я уверен, что вы «Знание, семантика статического члена класса - это очень, отличная от нестатического элемента.

+0

Ack, спасибо всем. Я думаю, что, наверное, слишком долго, и провел слишком много времени на Java в последнее время. Моя ошибка была такой глупой. То, что я хотел сделать, это объявить указатель - WordCloud * wc; Не оставляя *, я не создавал переменную указателя, и поэтому я был неистовым воплощением слова «облако». Я чувствую себя идиотом. Большое спасибо всем респондентам - ваши ответы очень информативны. – Sam

0

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

5

Нестатические переменные-члены в классе создаются экземпляром (т. Е. Вызывается их конструкторы) при построении содержащего объекта. По умолчанию вызывается конструктор по умолчанию с нулевым аргументом, но компилятор предоставляет это только вам, если вы не предоставляете никаких явных конструкторов.

Решение состоит в том, чтобы явно построить wc объект в конструкторе FontTestingApp:

FontTestingApp::FontTestingApp() 
    : wc(&wordList) 
{ /* ... */ } 

А почему static изменения подавлена ​​ошибка, декларация static WordCloud wc; в определении класса не создает экземпляр объекта; он просто объявляет его точно так же, как extern WordCloud wc; в области файлов не будет создавать экземпляр класса. Действительно, статические переменные-члены, по существу, такой же, как extern глобалов, за исключением того, что их имя и контроля доступа правила основаны на классе они находятся в

Если бы вы на самом деле экземпляр переменной статического члена в некотором .cpp файле с:.

WordCloud FontTestingApp::wc; 

Тогда у вас была бы ошибка. Конечно, вы могли бы передать в параметрах конструктора для решения этой проблемы:

static map<string, int> dummy_word_source; 
WordCloud FontTestingApp::wc(&dummy_word_source); 

Обратите внимание, что если вы не создаете экземпляр переменной вообще, вы, конечно, получите ошибку компоновщика, если вы пытаетесь ссылаться на нее в другом месте.

+0

Очень ясный ответ - thankyou bdonlan – Sam

0

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

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

Чтобы устранить эту проблему, предоставьте конструктор для вашего класса FontTestingApp, который использует список инициализации члена, чтобы вызвать соответствующий конструктор для члена данных WordCloud.

0

Вы не должны ставить элемент wc.

Вместо этого вы должны вызвать конструктор для класса явно из списка инициализации конструктора FontTestingApp, как и это:

FontTestingApp::FontTestingApp(): wc(&wordList) { 
    // more initialization 
} 
1

Если вы объявите конструктор с параметрами и использование хочет конструктора без параметров, которые вы должны объявить последний явно. Но вы не используете конструктор wc с параметрами. Если вы хотите сделать это, вы должны написать что-то вроде этого:

class FontTestingApp : public AppBasic 
{         
    public: 
... 
    FontTestingApp() : wc(&wordList) {} 
    map<string, int> wordList; 
    WordCloud wc;  
}; 

Использование «статические» заявление только заявление члена данных, но не определение. Вот почему ваш код скомпилирован без ошибок.

Смежные вопросы