Если вы пытаетесь использовать переменные, которые являются глобальными, и вы знаете, что они являются постоянным значением, таким как PI, я бы воздержался от использования как локальных глобальных, так и макросов #define. Это вопрос предпочтения, но со временем я узнал, что лучше использовать и более элегантно объявлять их как static const type name;
в файле заголовка и устанавливать значение соответственно в файле cpp. Я также не предпочитаю иметь кучу оборванных ценностей или основных методов, висящих вокруг, поэтому я обычно группирую подобные типы значений и методы и содержал их в классе, объявляющем их статическими. Вот пример:
Utility.h
#ifndef UTILITY_H
#define UTILITY_H
#include <iostream>
#include <string>
#include <stdio.h>
class Utility {
public:
static void pressAnyKeyToQuit();
static std::string& toUpper(std::string& str);
static std::string& toLower(std::string& str);
private:
Utility(); // Not Implemented - This class is not an object and can not be declared.
Utility(const Utility& c); // Copy Constructor - Not Implemented
Utility& operator=(const Utility&c); Assignment Operator - Not Implemented
}; // Utility
#endif // UTILITY_H
Utility.cpp
#include "Utility.h"
// -------------------------------------------------------------------------
// pressAnyKeyToQuit()
void Utility::pressAnyKeyToQuit() {
std::cout << "Press any key to quit" << std::endl;
_getch();
} // pressAnyKeyToQuit
// -------------------------------------------------------------------------
// toUpper()
std::string& Utility::toUper(std::string& str) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
return str;
} // toUpper
// -------------------------------------------------------------------------
// toLower()
std::string& Utility::toLower(std::string& str) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
return str;
} // toLower
Для использования этих функций здесь приводится пример:
main.cpp
#include <iostream>
#include <string>
#include "Utility.h"
int main() {
std::string strHello("Hello World!");
std::cout << strHello << std::endl;
std::cout << Utility::toLower(strHello) << std::endl;
std::cout << Utility::toUpper(strHello) << std::endl;
Utility::pressAnyKeyToQuit();
return 0;
} // main
С этим типом сдерживания является незаконным, чтобы сделать это:
int main() {
Utility util;
util.pressAnyKeyToQuit();
} // main
Это не потому, что конструктор утилита по умолчанию является частным или недоступен, однако любой тип функции или переменной, которая объявлена как static можно вызвать через оператор разрешения области. Ниже приведен пример константных переменных, которые будут считаться глобальными.
GeneralMath.h
#ifndef GENERAL_MATH_H
#define GENERAL_MATH_H
class Math {
public:
static const float PI;
static const float PI_HAVLES;
static const float PI_2;
static const float ZERO;
inline static bool isZero(float fValue);
template<typename T>
inline static void swap(T& value1, T& value2);
private:
Math();
Math(const Math& c); // Not Implemented
Math& operator(const Math& c); // Not Implemented
}; // Math
#include "GeneralMath.inl"
void dummy(); // does nothing used to have a method in the *.cpp file
#endif // GENERAL_MATH_H
GeneralMath.inl
// -------------------------------------------------------------------------
// isZero()
inline bool Math::isZero(float fValue) {
if ((fValue > -ZERO) && (fValue < ZERO)) {
return true;
}
return false;
} // isZero
// -------------------------------------------------------------------------
// swap()
template<class T>
inline void Math::swap(T& value1, T& value2) {
T temp;
temp = value1;
value1 = value2;
value2 = temp;
} // swap
GeneralMath.каст
#include "GeneralMath.h"
const float Math::PI = 4.0f * atan(1.0f); // tan(pi/4) = 1
const float Math::PI_HALVES = 0.5f * Math::PI;
const float Math::PI_2 = 2.0f * Math::PI;
const float Math::ZERO = static_cast<float>(1e-7);
void dummy(){return;}
Используя его в качестве примера:
main.cpp
#include <iostream>
#include "Utility.h"
#include "GeneralMath.h"
int main() {
float value = 3.14957;
if (Math::isZero(value - Math::PI)) {
std::cout << "true" << std::endl;
} else {
std::cout << "false" << std::endl;
}
Utility::pressAnyKeyToQuit();
return 0;
} // main
Я предпочитаю этот подход, так что, когда общие автономные методы и постоянные переменные часто используются в нескольких файлы и имеют подобную группировку, у вас нет кучи #defines или глобальных объявленных везде.
Теперь, с другой стороны, если определенный объект класса, который вы создаете, зависит от уникального для него уникального значения констант, то вы можете иметь глобальное значение в его файле * .h или * .cpp, но я все равно останусь объявите его как static const type name;
Простота этого заключается в том, чтобы включить * .h-файл, где это необходимо, и использовать имя класса с оператором разрешения области, за которым следует константная переменная или статический метод, где это необходимо.
Вы также можете сделать подобный подход, не используя класс, а не объявлять их как статические, содержа их в пространстве имен, но это может вызвать проблемы, поскольку другие разработчики могут иметь одно и то же пространство имен, и это может создавать конфликты для разрешения имен , Вот почему я предпочитаю подход класса и объявляю его как статические члены.
Помните, что эти классы не являются объектами, и они не могут быть построены, и все участники должны быть статичными!
'#define global_variable_1 = 1;' - серьезно? Это настоящий код или вы просто дали нам приблизительное? –
Прекрасно добавлять эти строки препроцессора в отдельный файл .h и включать файл в заголовки. Никакой код компиляции не должен быть в файлах с самоподготовкой –
@PaulR Это, по-видимому, пример для демонстрации моей «проблемы»! – Thanos