Davlog
Davlog

Reputation: 2238

Extern Variable - where should I place it?

I'm developing a small progran. I use Qt for the GUI. I have 2 Forms / Classes. MainWindow and AddProductDialog.

There is a variable (a std::string to be exact) which I need in both of them. I need to define it in an Event of AddProductDialog (e.g. std::string decl = "";) and I need to use the value of it in a function of my MainWindow.

I thought I could place this variable in a header file which each of them will include but apparently it doesn't work.

Now it works but I don't think that's a good style. I declared and defined it in my 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);
}

This works of course. But is there a way to declare this variable in a header and include it so I can use it?

I tried something like this at first but it always caused an error :

header

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

mainwindow

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

addproductdialog

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

Upvotes: 2

Views: 221

Answers (5)

harper
harper

Reputation: 13690

You treat the header file and the corresponding source file as a module that implements somethings. Per convention you name them similar, e.g. MainWindow.h and MainWindow.cpp.

You should add an extern declaration in the header file for each variable that is defined in that module and shall be public visible to other modules. Every module that needs to know the type or the instance name of the variable just includes the required header file. Or course the implemention source includes its own header file.

Example:

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

The variable addProductDialog is defined extern in the header file. When the compiler processes the compilation unit MainWindow.cpp it first "sees" it as extern declaration later it gets the actual definition. That's no problem at all and there is no need to fiddle with preprocessor constructs like compilation unit specific defines.

I don't know how the variable descr is related to all the code in your program. You will find a better names for the files. Therefore I choosed intentionally an ugly file name to encourage to use a better one.

Upvotes: 1

Balog Pal
Balog Pal

Reputation: 17163

In my guidelines you're strictly forbidden to use extern declaration in an implementation file. Either in function block or namespace scope.

Externs must appear in a .h file that is included by client and the file that defines it. That makes it easier to discover discrepancy in type or attributes. Also allows easier maintenance, as you limit redundancy to a single instance.

Upvotes: 5

user93353
user93353

Reputation: 14039

You can do this.

In the header file

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

In main.cpp

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

In the other .cpp files

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

So it gets defined in only one .cpp file & gets externed in all the others.

Upvotes: -1

Mats Petersson
Mats Petersson

Reputation: 129374

This:

 descr = "whatever";

must be within a function or as an initializer where the function is defined.

And I would put the extern std::string descr; in a header file. The definition can go wherever you feel it "belongs".

Upvotes: 0

Julien Lopez
Julien Lopez

Reputation: 1021

I'm not sure I understand your problem very well, but couldn't you just make descr a private member of addproductdialog, have a getter for the mainwindow to read it once the dialog ends and is accepted?

Upvotes: 4

Related Questions