3

我正在尝试将旧的 Fortran 77 代码转换为 C++,并且大多数变量都在 Common 块中声明,例如:

COMMON/BLK1/Gw(200),Eta(4096),t(4096),Phi(200),w(200)
COMMON/BLK2/g,dw,Vel,M,dt,N,Ioutp1,Ioutp2
COMMON/BLK3/Hs,Std,E,Hs1,Tdt

据我了解,通用块仅用于使变量在整个程序中的不同子例程中可访问。因此,在 C++ 程序中,我是否能够使用变量(在主程序之外)创建结构并以这种方式将变量作为结构的成员调用?

4

3 回答 3

2

根据我对本页COMMON 的理解,C++ 等效项是创建一个名为common.h(带有包含保护)的文件,其中包含:

 namespace BLK1
 {
      int const Gw = 200;
      int const Eta = 4096;
      int const t = 4096;
      int const Phi = 200;
      int const w = 200;
 }

 namespace BLK2
 {
      extern int g, dw, Vel, M, dt, N, Ioutp1, Ioutp2;
 }

 namespace BLK3
 {
      extern int Hs, Std, E, Hs1, Tdt;
 }

此外,.cpp您需要在项目中的一个文件中为任何非常量提供定义,例如foo.cpp

 #include "common.h"

 namespace BLK2
 {
      int g, dw, Vel, M, dt, N, Ioutp1, Ioutp2;
 }

 namespace BLK3
 {
      int Hs, Std, E, Hs1, Tdt;    // initialized to 0 by default
 }

您可能希望使用与 不同的类型int,例如unsigned long。我假设初始化的值是常量;如果不是,则更int const改为extern int并删除初始化程序。初始化程序必须进入.cpp文件中的定义。

避免在头文件中声明非常量、非外部变量的错误;如果标头包含在两个不同的单元中,这会导致未定义的行为。

例如,您可以通过编写BLK1::Eta来访问这些变量。

正如您推测的那样,使用 astruct而不是命名空间可能会被认为更整洁,尽管您仍然必须创建extern在标头中声明并在一个.cpp文件中定义的结构的实例;如果您是 C++11 之前的版本,那么提供初始化程序会更烦人。

(当然,更好的办法是重构代码以不使用全局变量。但作为直接翻译的第一步可能会很有用)。

于 2014-09-15T12:17:43.710 回答
2

同名的公共块在内存中相互重叠。您可以分配一块内存,并将类型转换指针指向它。另一种选择是在联合中声明它们。这就是为什么发明了工会。当然,一旦你的 union 建立起来,你就可以在其他模块中使用 extern。

将以下内容放入公共标头并将其实例放入模块 1。添加一个 extern 以便在模块 2 中看到它。

union blk1
{
    struct module_1_view
    {
        double gw(200);
        double eta(4096);
        double t(4096);
        double phi(200);
        double w(200);
    } 

    struct module_2_view
    {
        double parameters(8592);   // 200 + 4096 + 4096 + 200
        double w_status(200);
    } 
}

想象一下,模块 1 负责将文件中的一些双精度值加载到 module_1_view 中的变量中。一旦加载并验证了这些参数,就会调用模块 2,它从模块 2 视图访问参数。几乎所有这些都通过参数变量访问,除了 w_status,它实际上是 200 个指示参数成功或验证的指标。

关键是模块 1 和 2 访问相同的内存块(因此是联合),并且它们使用自己的一组变量名。

于 2015-02-17T02:01:20.110 回答
-1

我不能直接与 Fortran 对话,但如果您想在整个 c/c++ 程序中访问变量,extern 就是您要查找的关键字。

Extern 是一种 C 风格的数据共享方式。C++ 会将您推向 OO 设计,其中与许多对象紧密耦合的变量不是好的 OO。

如果您尝试在遗留代码之上执行 C++ 操作,有时静态方法(传递给您的 C++ 类的指针)可以充当包装器。下面是一个简单的例子:

extern int _magicVariable;

static void call( void* klass )
{
  ((MyClass*)klass)->functionCall( _magicVariable );
}

在 MyClass 中,您需要将 void call( void* ) 命名为朋友。现在遗留代码可以使用指向您的类的指针调用(void*),将_magicVariable 传递到您的OO 设计中。从那里 c++ 将做它的事。

底线是你有很多方法来完成任务,尝试根据你想要的代码结构做有意义的事情。

于 2014-09-15T11:35:01.830 回答