Ошибки компоновщика с закрытыми членами класса в заголовочном файле

Я пытаюсь создать проект в Visual Studio 2008. Я получаю кучу ошибок компоновщика, которые меня очень беспокоят. Мое приложение представляет собой консольное приложение Win32, использующее только собственный ANSI C++.

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

Я предполагаю, что это, вероятно, простой факт С++, о котором я еще не знаю?

Пример: я обращаюсь к членам SingleDelay в определениях функций классов-членов SingleDelay в файле Delays.cpp. то есть:

SingleDelay::tick(void *output, void *input, int nbufferFrames)<br>{
   //.. code here<br>
   x = dry * castInput + wet * castInput;<br>
}

Ошибка 38 error LNK2001: неразрешенный внешний символ "private: static double SingleDelay::dry" (?dry@SingleDelay@@0NA) Delays.obj testall

Определение SingleDelay в Delays.h:

class SingleDelay{

    private:  
        static double dry; //% of dry signal<br>
        static double wet; //% of wet signal<br>
        static unsigned int delay; //Delay in milliseconds<br>
        static int delayCell; //Index in the delayBuffer of the delay to add<br>
        static double *delayBuffer; //Delay buffer is 1 second long at sample rate SAMPLE_RATE<br>
        static unsigned int bufferCell; //Pointer to the current delay buffer cell<br>

    public:

        //Tick function
        static void tick(void *output, void *input,int nBufferFrames);

        //Set and Get functions
        static void setSingleDelay(double tDry, double tWet, unsigned int tDelay);
        static void setSingleDelay(void);

        static void setDry(double tDry);
        static void setWet(double tWet);
        static void setDelay(unsigned int tDelay);

        static double getDry(){ return dry;}
        static double getWet(){ return wet;}
        static unsigned int getDelay(){ return delay;}

        static void initializeDelayBuffer(){
            destroyDelayBuffer();

            delayBuffer = new double[bufferLength];
        }
        static void destroyDelayBuffer(){
            delete[ ] delayBuffer;
        }
};

person Rich    schedule 01.03.2009    source источник
comment
Можете ли вы перечислить ошибку ссылки, которую вы получаете?   -  person Andrew Khosravian    schedule 01.03.2009
comment
Yyeha, возможно, вы захотите опубликовать точные ошибки компоновщика, чтобы мы могли дать вам предположения, в чем может быть причина.   -  person Franci Penov    schedule 01.03.2009
comment
Да, я только что понял это, я добавил два примера ошибок и немного своего связанного кода.   -  person Rich    schedule 01.03.2009


Ответы (4)


  1. Может быть, вы не добавили библиотеку и не включили пути к библиотеке, которую используете, в определения проекта?
  2. На ошибки C++ всегда интересно смотреть. Или не. В любом случае, вы где-нибудь инициализируете свои статические переменные? Вам нужно сделать это где-нибудь в файле .cpp. И не забывайте использовать статические переменные с осторожностью. На самом деле они являются замаскированными глобальными переменными и могут затруднить будущие изменения, такие как многопоточность.
person Gilad Naor    schedule 01.03.2009
comment
2. Да, я думал, что проблема будет вызвана инициализацией статических переменных. Это должно быть сделано в .cpp или я могу сделать это после определения класса в .h файле? Инициализированные значения действительно будут перезаписаны, когда я фактически использую класс, поэтому они не очень важны для меня. - person Rich; 01.03.2009
comment
Что касается использования static, я сделал все свои классы задержки статическими, потому что для моих целей пользователь использует только один из каждого и только один за раз, поэтому создание экземпляра класса казалось излишним и, возможно, на самом деле доставляло мне проблемы в его собственном которого я избегал, становясь статичным. - person Rich; 01.03.2009
comment
Хорошо, я попытался снова инициализировать переменные, и на этот раз это сработало. Казалось, я делал небольшие ошибки в первый раз. Спасибо всем за помощь, иногда требуется, чтобы другие подтолкнули вас попробовать одно и то же дважды =). - person Rich; 01.03.2009
comment
Удачи!!! Вы можете проверить эту ссылку: parashift.com/c++- faq-lite/ctors.html#faq-10.11 Также прочитайте пункт ниже, потому что порядок инициализации статических переменных не определен и может создать случайные проблемы, если вы не будете осторожны. - person Gilad Naor; 01.03.2009
comment
Пожалуйста, проверьте ответ greyfade, так как он правильный. Когда вы определяете статические атрибуты в заголовке, вы не резервируете для них память, а просто объявляете переменную (аналогично внешнему объявлению). Вы должны объявить переменные в одной единице компиляции. - person David Rodríguez - dribeas; 01.03.2009

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

Все статические элементы данных должны иметь определение в файле .cpp где-то.

Ошибка 38 error LNK2001: неразрешенный внешний символ "private: static double SingleDelay::dry" (?dry@SingleDelay@@0NA) Delays.obj testall

Компоновщик сообщает вам, что для этой переменной нет определенного хранилища. Эта строка должна появиться где-то ровно в одном файле .cpp:

double SingleDelay::dry = 0.0;
person greyfade    schedule 01.03.2009

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

class SingleDelay{
 ...
int tick(void *output, void *input, int nbufferFrames)
{ //.. code here
x = dry * castInput + wet * castInput;
}
 ...
}
person Roman    schedule 30.10.2010

Вам нужно добавить файлы .cpp и .h в файл .vcproj.

person Vinay    schedule 01.03.2009
comment
я не уверен, что это значит. Я не редактирую свои файлы .vcproj вручную с помощью текстового редактора или чего-либо еще. Я перетащил все необходимые включаемые файлы в раскрывающееся меню файлов заголовков в обозревателе решений для моего проекта. Я также помещаю файлы *.cpp, которые я могу найти в меню «Исходные файлы». - person Rich; 01.03.2009
comment
Я проверил, и на самом деле мне не хватало некоторых файлов .cpp, которые, казалось, устраняли большинство моих ошибок компоновщика для # 2. Я до сих пор не знаю, что делать со всеми ошибками компоновщика типа № 1, которые я все еще получаю. - person Rich; 01.03.2009
comment
Перейдите в Project->Add Files, а затем выберите .cpp и .h вместо перетаскивания. - person Vinay; 01.03.2009