在头文件中包含全局变量 - c ++

时间:2015-10-06 06:00:16

标签: c++ global-variables header-files

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

<Window x:Class="YourWPFProject.SomeWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:common="clr-namespace:YourAssembly">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/YourAssembly;component/CommonResources.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <common:SomeCommonControl />

</Window>

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

所以我会有像

这样的东西
#include "header1.h"
#include "header2.h"
...

#define global_variable_1     1
#define global_variable_2     3
...

double function1(){
  <code>
{

double function2(){
  <code>
{

...

main(){
  <code>
}

我的问题是这样做是否合适,以及是否有另一种可能更好的方法来包含全局变量。

1 个答案:

答案 0 :(得分:0)

如果您尝试使用全局变量并且您知道它们是常量值(例如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默认构造函数是私有的或不可访问的,但是可以通过作用域解析运算符调用声明为static的任何类型的函数或变量。以下是将被视为全局变量的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

我更喜欢这种方法,这样当常见的独立方法和常量变量经常在多个文件中使用并具有相似的分组时,你就不会在任何地方声明一堆#defines或global。

另一方面,如果您正在创建的特定类对象依赖于它所特有的特定常量值,那么您可以在其* .h或* .cpp文件中使用全局,但我仍然会声明它是static const type name;

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

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

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