如何在C ++中的单独类或头文件中声明常量参数?

时间:2018-12-14 16:19:24

标签: c++

我的IDE是Microsoft Visual Studio 2017。

这是原始示例代码:

main.cpp

#include <iostream>
#include "Klasa_00.h"

using namespace std;

int main() {

    int const Number_0 = 234;
    float const Number_1 = 34.76;
    double const Number_2 = 98.78;

    cout << "Number_0 is:" << Number_0 << endl;
    cout << "Number_1 is:" << Number_0 << endl;
    cout << "Number_2 is:" << Number_0 << endl;

    system("Pause");
    return 0;
}

Klasa_0.cpp

#include "Klasa_00.h"

Klasa_00::Klasa_00()
{
}


Klasa_00::~Klasa_00()
{
}

Klasa_0.h文件

#pragma once
class Klasa_00
{

public:
    Klasa_00();
    ~Klasa_00();


};

我是C ++编程的新手,所以我需要有关编写代码的帮助。例如,在Fortran编程语言中,具有参数属性的所有变量都可以在单独的模块中声明,可以在主程序中轻松使用。 我想在这里学习的是在C ++或类似语言中使用这种编码原理的可能性。 因此,在我的案例中,我有三个变量要移入类Klasa_00中。 有这样做的方法吗?

2 个答案:

答案 0 :(得分:1)

为什么您需要为此上课?这似乎不合适。由于C ++是另一种语言,具有不同的习惯用法和概念,因此FORTRAN比较也不大可能取得成果。

在我看来,您应该将这些常量简单地放在头文件中。确保将它们设置为static const constexpr,以避免链接程序冲突。

// Constants.hpp
#ifndef MYLIB_CONSTANTS_HPP
#define MYLIB_CONSTANTS_HPP
#pragma once

static constexpr const int Number_0 = 234;
static constexpr const float Number_1 = 34.76;
static constexpr const double Number_2 = 98.78;

#endif

现在,您只需#include "Constants.hpp"在任何需要访问这些值的翻译单元中即可。

根据记录,做相同事情的老式C方法是使用#define

别忘了给这些常量赋予有意义的名称。

答案 1 :(得分:1)

正如其他人所说,您可能希望避免使用类将常量存储在其他文件中,而您可能只是希望将它们存储在标头中(可能带有名称空间,稍后再介绍)。话虽如此,我确实知道您可能想要一个属于一个类的常量,因此在答案的稍后部分,我还将对此进行介绍。

最简单的方法是这样声明和定义标头中的常量:

// YourHeader.h
#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

[...]
const int aConstNumber = 1;
static const int anotherConstNumber = 2;
constexpr int aConstExprNumber = 3;
static constexpr int anotherConstExprNumber = 4;
[...]

#endif

// main.cpp
#include <iostream>
#include "YourHeader.h"
int main()
{
    // You can simply access the variables by name as so:

    std::cout << aConstNumber << "\n"; // 1
    std::cout << anotherConstNumber << "\n"; // 2
    std::cout << aConstExprNumber << "\n"; // 3
    std::cout << anotherConstExprNumber << std::endl; // 4
}

这些变量在逻辑上都具有相同的行为,但是它们以不同的方式工作。使用const关键字声明的变量是在运行时定义的,并且保证不会更改。但是,使用constexpr关键字声明的变量是在编译时定义的。

因此,虽然这意味着如果您有多个类(例如ID)(ID不应更改,但应该是唯一的),则与const相比,constexpr更受欢迎(因为后者在这种情况下将无法工作)。

我们也来谈谈staticstatic表示在您的类中存在该变量的单个共享实例。因此,如果Bar类具有static int ID值,则Bar的所有实例共享相同的ID值。更改一次即可更改所有实例。尽管如果它是一个常数,则您将不能对其进行更改。

在您的情况下,如果要定义预定义且不会更改的常量,我强烈建议您使用constexpr,因为您可以使用这些变量来执行无法使用const变量(例如定义数组的大小)。

在继续进行之前,请考虑以下课程。

class Foo
{
public:
    const int a = 5; // Valid use of const.
    constexpr int b = 7; // Invalid use of constexpr, won't even compile!
    static constexpr int c = 10; // Valid use of constexpr.

    int arrA[a]; // ERROR: 'a' is defined at runtime, so you can't use it to define a size.
    int arrB[b]; // ERROR: You couldn't even define 'b', so this is not going to work...
    int arrC[c]; // VALID: 'c' is known by the compiler, and is guaranteed to only ever be 10!
}

值得注意的是,如果要访问ac(在类中声明和定义的唯一两个有效变量),则必须使用以下语法,而不是只是他们的名字:

// "Foo" is their class' name, and represents their parent namespace.
std::cout << Foo::a << "\n"; // 5
std::cout << Foo::c << std::endl; // 10

如您所见,constexpr int b = 7;无效。为什么呢它不应该被编译器看到并且可以正常工作吗?好吧,不。您会发现,问题在于您可能永远也不会实例化该类,对吗? const变量很好,因为它们是在运行时定义的,这意味着它们不必存在,一旦给它们赋值就不能更改。另一方面,constexpr必须确保它会存在,因为它必须存在并且在编译时才有效!

尽管在头文件中声明一个constexpr变量是完美的,但是如果要在类中声明一个变量,除非与它一起使用static关键字,否则它是行不通的!因为static关键字将使编译器知道,无论您如何实例化此类,变量的值将永远不会改变,并且由于{{1} }!

强烈建议您阅读this post,以了解constexprstatic合并后的作用。

  • 如果您具有仅在实例化后才恒定的“常数”,请使用constexpr
  • 如果您的常量永远不变,并且始终表示相同的值(例如PI等数学值),请使用const
  • 如果一个类的所有实例应该共享一个常量值,我建议使用constexpr 反对,因为它会在运行时定义,但始终具有相同的值, 对?只需使用static const即可。

最后,我在此答案的开头提到了名称空间。有时,您可能需要一组不一定属于一个类的关联常数。例如,虽然PI用于圈子中,但这并不一定意味着我每次想要PI时都想包含static constexpr类的标头。但是我不想在项目的名称空间中使用“原始” PI变量名称!那只是自找麻烦。相反,可以考虑将常量包围在circle块中,以模拟用于调用类成员的语法!

namespace

请注意,我们没有将// YourHeader.h #ifndef YOUR_HEADER_H #define YOUR_HEADER_H namespace MyConstants { constexpr int a = 1; constexpr int b = 2; } #endif // main.cpp #include <iostream> #include "YourHeader.h" int main() { std::cout << MyConstants::a << "\n"; // 1 std::cout << MyConstants::b << "\n"; // 2 } 与命名空间一起使用,因为我们没有使用staticclass,所以我们不需要,我们只是将它们包装起来在struct中,以避免命名冲突。 namespace在这里会做其他事情。有关更多信息,请参见this post

额外的注意:虽然可以将变量声明为static,但我不建议您使用它,因为它的作用与简单地声明constexpr const相同。请注意,constexpr与指针结合使用时,会将指针变成指向常量值的常量指针!有关更多详细信息,请参见this post