外部变量 - 我应该放在哪里?

时间:2013-06-07 16:22:10

标签: c++ extern

我正在开发一个小程序。我使用Qt作为GUI。我有2个表格/课程。 MainWindowAddProductDialog

我需要一个变量(确切地说std::string)。我需要在AddProductDialog的事件中定义它(例如std::string decl = "";)并且我需要在我的MainWindow的函数中使用它的值。

我以为我可以将这个变量放在一个头文件中,每个头文件都会包含但显然它不起作用。

现在它有效,但我认为这不是一个好的风格。我在main.cpp中声明并定义了它。

main.cpp:

//includes ...
...

std::string descr; //The variable I need

int main(){ /* blah blah */ }

MainWindow.cpp:

void MainWindow::on_AddProductOptions_clicked()
{
    extern std::string descr;
    AddProductDialog *adp = new AddProductDialog(this);
    adp->setModal(true);

    if(adp->exec() == QDialog::Accepted)
        _Description = descr; //_Description is a private variable of my MainWindow Class
}

AddProduct.cpp

void AddProductDialog::on_cmdOkay_clicked()
{
    extern std::string descr;
    descr = "";
    done(QDialog::Accepted);
}

当然这是有效的。但是有没有办法在标题中声明这个变量并包含它以便我可以使用它?

我最初尝试过类似的东西,但它总是导致错误:

标题

//include guard
extern std::string descr;
//include guard

主窗口

//include header
//...
std::string descr = "";
//...

addproductdialog

//include header
//...
extern std::string descr;
descr = "whatever";

5 个答案:

答案 0 :(得分:5)

在我的指南中,严格禁止在实现文件中使用extern声明。在功能块或命名空间范围内。

Externs必须出现在客户端和定义它的文件的.h文件中。这样可以更容易地发现类型或属性的差异。当您将冗余限制为单个实例时,还可以更轻松地进行维护。

答案 1 :(得分:4)

我不确定我是否理解你的问题,但是你不能只是让descr成为addproductdialog的私有成员,一旦对话结束并被接受,主窗口有一个getter来读取它吗?

答案 2 :(得分:1)

您将头文件和相应的源文件视为实现某些功能的模块。按照惯例,您将它们命名为相似,例 MainWindow.h MainWindow.cpp

您应该在头文件中为该模块中定义的每个变量添加一个extern声明,并且对于其他模块应该是公共可见的。每个需要知道变量类型或实例名称的模块都包含所需的头文件。或者,实现源包括它自己的头文件。

示例:

<强> MainWindow.h

class MainWindow
{
    public:
        void on_AddProductOptions_clicked();
};

extern MainWindow mainWindow;

<强> AddProduct.h

class AddProductDialog 
{
    public:
        void on_CommandOkay_Clicked();
};

extern AddProductDialog addProductDialog;

<强> SomeCommonDataIDontHaveANameFor.h

// If header files should include system header files or not is discussed elsewhere.
// I add this here to allow compiling of the sample code.
#include <string>

extern std::string descr;

<强> SomeCommonDataIDontHaveANameFor.cpp

#include "SomeCommonDataIDontHaveANameFor.h"

std::string descr;

<强>的main.cpp

#include "MainWindow.h"
#include "AddProduct.h"
#include "SomeCommonDataIDontHaveANameFor.h"

int main(void)
{
    mainWindow.on_AddProductOptions_Clicked();
    addProductDialog.on_CommandOkay_Clicked();
}

<强> MainWindow.cpp

#include "MainWindow.h"

AddProductDialog addProductDialog;

// add implemetation of AddProductDialog class

变量addProductDialog在头文件中定义为extern。当编译器处理编译单元 MainWindow.cpp 时,它首先将其视为extern声明,然后获得实际定义。这根本不是问题,也没有必要像编译单元特定的定义那样摆弄预处理器结构。

我不知道变量descr如何与程序中的所有代码相关。您将找到更好的文件名称。因此,我故意选择一个丑陋的文件名来鼓励使用更好的文件名。

答案 3 :(得分:0)

此:

 descr = "whatever";

必须位于函数内或定义函数的初始值设定项中。

我会将extern std::string descr;放在头文件中。定义可以在您认为“属于”的任何地方进行。

答案 4 :(得分:-1)

你可以这样做。

在头文件中

/* header.h */
MYEXTERN std::string descr;

在main.cpp

/* MYEXTERN doesn't evaluate to anything, so var gets defined here */
#define MYEXTERN 
#include "header.h"

在其他.cpp文件中

/* MYEXTERN evaluates to extern, so var gets externed in all other CPP files */
#define MYEXTERN extern
#include "header.h"

因此它仅在一个.cpp文件中定义。在所有其他人中被淹没。