You are not logged in.

#1 2010-11-06 21:05:43

Kosmonavt
Member
Registered: 2010-02-15
Posts: 100

[Solved] Dumb question about inclusion in C++

Hi all,

I'm writing quite a big C++ project (for me, surely :-), and I ran into big troubles with inclusion and declaration. To make access easier and faster to some often used data, I made it global and placed in a namespace. But then came troubles - I get errors about multiple declaration or about undefined variables. I simplified situation to the following sample:

-------main.cpp:

#include <iostream>
#include "header.hpp"

int main()
{
        using std::cout;
        using std::endl;

        cout << "Test" << endl;
        std::string m("a message");
        SetMessage(m);
        PrintMessage();
        return 0;
}

-------header.hpp:

#ifndef HEADER_HPP
#define HEADER_HPP

#include <iostream>

void PrintMessage();
void SetMessage(std::string msg);

namespace module
{
        std::string message;
}

#endif          // HEADER_HPP

-------header.cpp:

#include "header.hpp"

void SetMessage(std::string msg)
{
        using namespace module;
        message = msg;
}
void PrintMessage()
{
        std::cout << "Message is: " << module::message << std::endl;
}

I googled but the only solution I found was using extern keyword. But namespace module is internal from header.* standpoint and isn't used/mustn't be defined in main.cpp. Now I simply haven't got any idea how to solve it.

How can it be corrected?

Last edited by Kosmonavt (2010-11-07 09:15:51)

Offline

#2 2010-11-06 22:24:35

Allan
Pacman
From: Brisbane, AU
Registered: 2007-06-09
Posts: 11,487
Website

Re: [Solved] Dumb question about inclusion in C++

read about inclusion guards.

Offline

#3 2010-11-07 00:05:27

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 20,296

Re: [Solved] Dumb question about inclusion in C++

It looks to me like your inclusion guards are okay. 
Aside from exposing the module namespace in header.hpp, it looks okay to me.

Does this example fail to compile? Where and how?

As to the module namespace, i would define it in header.cpp as main has no need to know.


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

#4 2010-11-07 07:12:50

Zeist
Arch Linux f@h Team Member
Registered: 2008-07-04
Posts: 532

Re: [Solved] Dumb question about inclusion in C++

Since you only want a single instance of message anyway I think the easiest would be to just make it a "static std::string", that makes it compile and run fine for me.


I haven't lost my mind; I have a tape back-up somewhere.
Twitter

Offline

#5 2010-11-07 09:15:33

Kosmonavt
Member
Registered: 2010-02-15
Posts: 100

Re: [Solved] Dumb question about inclusion in C++

To Allan: there are header guards.

To ewaller: basically it's true, but this namespace is not an implementation, but some sort of declaration. So it's more logical to place it in header. This sample threw "multiple declaration" linker error while building it with g++ -Wall $(SOURCES).

Looks like it's the following sort of problem: preprocessing being run on main.cpp includes into it's code all the header.hpp, similarly header.hpp is included in header.cpp. Still, strange that it wasn't parsed as a whole.

And yes, static declaration of all variables/constants in namespaces helped (thanks Zeist!). It was so easy that I hadn't thought about it. Marking as solved.

Last edited by Kosmonavt (2010-11-07 09:17:57)

Offline

#6 2010-11-07 19:28:52

tavianator
Member
From: Waterloo, ON, Canada
Registered: 2007-08-21
Posts: 859
Website

Re: [Solved] Dumb question about inclusion in C++

"static" is probably not what you want, for two reasons:
1) C++ supports anonymous namespaces, which are more "the C++ way."  To use them, you'd write:

namespace module {
  namespace {
    std::string message;
  }
}

2) If you make a static/anonymous std::string in header.hpp, there's a useless std::string added to every translation unit that includes it.  Instead, only declare and define module::message in header.cpp itself.  That would look like this:

header.hpp:

#ifndef HEADER_HPP
#define HEADER_HPP

#include <iostream>

void PrintMessage();
void SetMessage(std::string msg);

#endif          // HEADER_HPP

header.cpp:

#include "header.hpp"

namespace module { // nb: you don't really need this namespace now
  namespace {
    std::string message;
  }
  // Alternatively:
  // static std::string message;
}

void SetMessage(std::string msg)
{
        using namespace module;
        message = msg;
}

void PrintMessage()
{
        std::cout << "Message is: " << module::message << std::endl;
}

Offline

Board footer

Powered by FluxBB