在头文件中包含全局变量

Include global variables in header file - c++

本文关键字:包含 全局变量 文件      更新时间:2023-10-16

目前我正在使用相当大的一段代码来分析数据。在这段代码中,除了分析本身,我还包括了一些将在分析中使用的函数,一些与对象和一些全局变量相关的函数。我的代码有以下结构

#include "header1.h"
#include "header2.h"
...
#define global_variable_1     1
#define global_variable_2     3
...
double function1(){
  <code>
{
double function2(){
  <code>
{
...
main(){
  <code>
}

现在我想让我的代码更优雅,更复杂,可编程正确。我正在考虑制作一个头文件,其中将包括我正在使用的头文件和一些函数,第二个头文件与其余的函数和最后一个头文件,将包含我使用的全局参数。

因此我将写入像

这样的内容
#include "headers.h"
#include "functions.h"
#include "variables.h"
main(){
  <code>
}

我的问题是,它是否可编程适当这样做,如果有另一个,也许更好的方式来包括全局变量

如果你试图使用全局变量,并且你知道它们是一个常量值,如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

这将失败,因为Utility默认构造函数是私有的或不可访问的,但是可以通过作用域解析操作符调用声明为静态的任何类型的函数或变量。下面是一个将被视为全局变量的const变量的示例。

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.cpp

#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

我更喜欢这种方法,这样当常见的独立方法和常量变量经常在多个文件中使用并且具有类似的分组时,您就不会到处声明一堆#define或global。

另一方面如果你要创建的特定类对象依赖于特定的常量值而这个常量值是唯一的那么你可以在*.h或*.cpp文件中使用全局变量但我还是会声明它为static const type name;

这样做的简单之处在于在需要的地方包含*.h文件,并在需要的地方使用类名和作用域解析操作符,后面跟着const变量或静态方法。

您也可以使用类似的方法,不使用类,也不通过将类包含在名称空间中而将其声明为静态,但这可能会导致问题,因为其他开发人员可能具有相同的名称空间,这可能会在解析名称时产生冲突。这就是为什么我更喜欢类方法并将它们声明为静态成员的原因。

记住这些类不是对象,它们不能被构造,所有的成员必须是静态的!