2017-01-04 9 views
2

Я новичок в C++, и у меня есть трудности с моим проектом.Объявление и определение разделительной функции или удаление нового оператора в заголовке?

Super.h

#pragma once 
#include <iostream> 

float *list=new float[10]; 

class Super{ 
public: 
    void function(){} 
}; 

хиджры

#pragma once 
#include "Super.h" 

class A{ 
public: 
    void function(); 
}; 

a.cpp

#include "A.h" 
void A::function(){ 
    std::cout<<"Working A!"<<std::endl; 
} 

main.cpp

#include "A.h" 

int main(int argc, const char * argv[]) { 
    A a; 
    a.function(); 
    return 0; 
} 

Этот код не компилируется (лязг: ошибка: команда линкер потерпела неудачу с кодом выхода 1 (использование -v, чтобы увидеть вызов)), и я нашел, если я удалю

float *list=new float[10]; 

в Super.h, он составлен.

Однако, мне нужен массив, который можно получить доступ в классе А. Таким образом, я перепробовал много способов, и нашел, что это может быть скомпилирован, если я оставлю буев, и объединить Ах и a.cpp, как

//Super.h  

float *list=new float[10]; 

class Super{ 

public: 
    void function(){} 
}; 

------------------------------------ 
// A.h 

#pragma once 
#include "Super.h" 


class A{ 

public:  
    void function(); 
}; 

void A::function(){ 
    std::cout<<"Working A!"<<std::endl; 
} 

Должен ли я комбинировать A.cpp и Ah? или мой дизайн плохой? Я использую XCode 8.

+1

Это глобальная переменная. Это плохая практика. Может быть, вы могли бы рассказать нам немного больше о том, что вы хотите делать с «списком», может ли он быть членом или статическим членом «A», например? –

+1

Да, имея глобальную переменную 'float * list = new float [10];' плохой дизайн. Но фактическая причина заключается в том, что вы объявляете глобальную переменную в файле заголовка. –

+2

Нет, фактическая причина заключается в том, что вы объявляете глобальную переменную в файле заголовка, затем включаете этот заголовочный файл в несколько единиц перевода. –

ответ

0

В вашем фактическом коде «line» объявляется в Settings.h и используется в его функции drawPixel.

Единственное место, что он используется в main.cpp я собираюсь обсудить эти вопросы в обратном порядке, поэтому наше обсуждение может сделать больше смысла:

  • Cleanup: delete[] pixels Вы должны использовать vector<float> вместо так вы избегаете всех проблем, связанных с динамической памятью:
    1. Что делать, если drawPixel вызывается после очистки?
    2. Что делать, если ваш код завершается с ошибкой?
    3. Как вы гарантируете, что ваша функция main не выйдет раньше и пропустит это?
  • Использование: glDrawPixels(width, height, GL_RGB, GL_FLOAT, pixels) Конечный glDrawPixels параметр типа void* Так что, если вы правильно заменить pixels с vector<float> вы можете сделать неявное преобразование, передавая data(pixels)
  • Initialization: fill_n(pixels, width*height * 3, 1.0f) Вместо того, в Settings.h, это где pixels должны быть определены: vector<float> pixels(width * height * 3, 1.0F) вам нужно, чтобы сделать эти изменения в вашей системе, чтобы избежать глобальной переменной:
    1. Все экземпляры void draw() должны быть изменены, чтобы void draw(vector<float>& pixels) и когда любой draw метод называется pixels будет аргумент
    2. void drawPixel(const int& i, const int& j, const float& red, const float& green, const float& blue) должен быть изменен на void drawPixel(vector<float>& pixels, const int i, const int j, const float red, const float green, const float blue) и любой вызов функции drawPixel должны pixel, как это 1 улица аргумент
    3. void drawLine(const int& i0, const int& j0, const int& i1, const int& j1, const float& red, const float& green, const float& blue) должен быть изменен на void drawLine(vector<float>& pixels, const int i0, const int j0, const int i1, const int j1, const float red, const float green, const float blue) и любой вызов функции drawLine должны pixel, как это 1-й аргумент
+0

Спасибо за ваш ответ доброты! У меня есть несколько вопросов. Есть ли разница между 'std :: vector пикселей (ширина * высота * 3,0.0f);' и 'float * list = new float [10];'? Я думал, что переменные, определенные за пределами {}, называются глобальными переменными ... – jino

+0

@JinoPark Вы правы, что переменные, объявленные в области пространства имен (а не в области функции), являются глобальными. Не объявляйте об этом. В моей последней маркерной точке я предлагаю вам определить «пиксели» в области «main».Вот почему вам нужно добавить его в качестве ссылочного параметра, который должен быть передан из 'main' в любую функцию, которая ему понадобится (даже если она передается несколько раз, например, в случае drawPixel или' drawLine'). Что касается того, почему вы хотите использовать «вектор» вместо динамически распределенного массива, это обсуждается в первом выпуске, но в основном так, что стандарт будет управлять вашей памятью для вас. –

+0

Он работает, когда я делаю пиксельный вектор в своей основной функции. Однако он все еще не компилируется, когда я разделяю определение и объявление функции, например, на Line.h и Line.cpp. Я обнаружил, что _duplicate symbol error_ вызывается, когда глобальная переменная включается более двух раз в заголовок. Я изменил 'const int width = 640' на' #define Width 640', чтобы удалить глобальные переменные, но он все еще не работает ... Также я помещал '#pragma once', я думаю, что заголовки не дублируются. – jino