这是一个描述我当前情况的最小工作示例。文件main.cpp
#include <iostream>
void print_from_external_file();
using namespace std;
int main( int argc, char* argv[])
{
print_from_external_file();
return 0;
}
包含print_from_external_file()
的文件#include <iostream>
using namespace std;
namespace
{
int a;
}
void print_from_external_file()
{
cout << a << endl;
}
这是我的目标:我希望通过命令行运行此程序,如“test.exe 2”。我希望将整数2加载到外部文件中的变量 a 中。有没有办法实现这一点,而无需使用argv [1]调用print_from_external_file()?换句话说,“a”可以自动赋值“2”吗?
答案 0 :(得分:2)
如果您可以更改定义变量“a”的文件,则将该变量放入非匿名命名空间或在同一文件中定义导出的getter(下面的same1.cpp或same2.cpp)。否则你将无法按照自己的方式进行设置。
some1.cpp:
namespace {
int a;
}
void set_a(int a_) { a = a_; }
some2.cpp:
namespace some {
int a;
}
main.cpp中:
#include <cstdlib>
namespace some {
extern int a;
}
int main(int argc, char** argv) {
assert(argc == 2);
some::a = atoi(argv[1]);
// or: set_a(atoi(argv[1]));
return 0;
}
答案 1 :(得分:2)
您必须为命名空间命名。未命名的命名空间与其翻译单元相关联,因此您将无法从其他单元访问其中的变量。
你的.cpp:
#include <iostream>
#include <stdlib.h>
#include "main.h"
void print_from_external_file();
using namespace std;
using ddd::a;
int main( int argc, char* argv[])
{
a = atoi( argv[1] );
print_from_external_file();
return 0;
}
你的.h:
#include <iostream>
using namespace std;
namespace ddd
{
int a;
}
using ddd::a;
void print_from_external_file()
{
cout << a << endl;
}
或者,您可以删除命名空间,并在.cpp文件中使用extern int a
来访问变量:
的.cpp
#include <iostream>
#include <stdlib.h>
#include "main.h"
void print_from_external_file();
using namespace std;
extern int a;
//the rest goes unchanged
·H:
#include <iostream>
using namespace std;
int a;
//the rest goes unchanged
答案 2 :(得分:1)
我认为您正在寻找的是使用 extern 关键字。
如果您在主a
中声明为 extern 变量,那么您应该没问题。
#include <iostream>
void print_from_external_file();
using namespace std;
extern int a;
int main( int argc, char* argv[])
{
//set value of a
a = atoi(argv[1]); //atoi is deprecated but is easier to use in an example
print_from_external_file();
return 0;
}
修改强>
在第二个文件中,您需要删除命名空间或为其指定名称。 我使用以下代码测试第二个文件,它按预期工作
#include <iostream>
using namespace std;
namespace
{
int a;
}
void print_from_external_file()
{
cout << a << endl;
}
编辑2:使用命名空间的代码
文件1
#include <iostream>
void print_from_external_file();
using namespace std;
namespace TEST
{
extern int a;
}
int main( int argc, char* argv[])
{
//set value of a
TEST::a = atoi(argv[1]); //atoi is deprecated but is easier to use in an example
print_from_external_file();
return 0;
}
文件2
#include <iostream>
using namespace std;
namespace TEST
{
int a;
}
void print_from_external_file()
{
cout << TEST::a << endl;
}
答案 3 :(得分:0)
是的,你可以。
对于整数,您必须使用std::atoi().
所以代码变成:
int a = std::atoi(argv[1]);
答案 4 :(得分:0)
如果您使用的是Windows,
namespace
{
int nArgs = 0;
int a = wtoi(CommandLineToArgvW(GetCommandLineW(), &nArgs)[0]);
}
为了简洁起见,我跳过了所有错误检查。
答案 5 :(得分:0)
标准做法是使用argv
来访问命令行参数。您可能会在某些架构上发现还有其他方法可以做到这一点,但它们不太可能是可移植的,并且似乎没有太多理由不遵循标准做法。要将值读入int,您可以使用strtol
long n = strtol( argv[1], NULL, 0 );
(请注意,我倾向于使用strtol
到atoi
,因为您可以更多地控制输入和错误处理 - 但不是很多)
您还可以按如下方式使用流:
istringstream ss( argv[1] );
long n;
ss >> n;
关于你正在尝试做什么,有两件事让我感到担忧:首先你需要一个变量值,在运行时设置封装在一个函数中。逻辑上,这将使您的代码不易维护,因为您的函数和外部影响(命令行参数)之间将存在不可见的依赖关系 - 因此您的函数的确定性属性将受到损害。实际上,这将使测试您的功能变得更加困难 - 尤其是使用自动单元测试,因为在运行之前无法以编程方式设置值。
其次,好像要复合它,您正在寻求将a
变量的范围限制在未命名的命名空间中的编译单元。这有两个不良影响。首先,从自动化UT的角度来看,没有任何测试工具或任何其他代码能够再次看到这个变量,这非常糟糕。其次,a
在您的编译单元中实际上变为“全局”。在这个编译单元的函数中,遵循如何以及何时使用a
对于维护代码的任何人来说都是一件令人头疼的事情将会非常棘手。我假设你没有使用会导致问题的多线程。
我很想知道你不想将argv[1]
传递给print_from_external_file()
的原因,但我认为这是最好的办法。如果您不认为可以直接将此变量作为字符串传递或转换为int,则可以考虑创建可以传入的命令行参数或配置对象:
configuration c( argc, argv ); // This contains the hard work of parsing the CL
print_from_external_file( c );
这隐藏了解析命令行的大部分艰苦工作。更好的是,它允许您为CL参数添加真正的含义。假设a
变量表示目录号,configuration
类的构造函数可以简单地执行此操作:
configuration::configuration( int argc, char* argv[] )
{
// ...
catalogNo_ = strtol( argv[1], NULL, 0 );
然后如果添加了访问者:
int configuration::get_catalog_no() const { return catalogNo_; }
然后在print_from_external_file()
我们正在做的事情变得更加明显:
void print_from_external_file( const configuration& c )
{
cout << c.get_catalog_no() << endl;
}