Using namespace in multiple VCL modules - c++

I'd like to use a certain namespace along with its functions to be used in several forms to have sort of shared functions. However, I am having linker problem.
Here is what I did - I created a new unit and inside of it I wrote in header file:
#ifndef MyHeaderH
#define MyHeaderH
namespace MyHeader
{
enum { SOMETHING1, SOMETHING2 };
void SomeFunction(int Param);
}
#endif
Of course, the actual function is defined in cpp file, the above is just from h file.
And the cpp file is as follows:
#pragma hdrstop
#include "MyHeader.h"
#pragma package(smart_init)
void SomeFunction(int Param)
{
//some code here
}
So in my main form Form1 I include the above in hpp file of Form1
MyHeader::SomeFunction(0);
This all compiles fine but the linker reports unresolved external. So obviously it doesn't see the namespace and function. How do I fix that?
As an additional question - if I use such function set in several forms, it should be all compiled just once and reused right (it won't have several copies of same functions I guess?)

You probably forgot to put the function definition in the namespace.
It's either done like you do in the header file, but with a function body:
namespace MyHeader
{
void SomeFunction(int Param)
{
// ...
}
}
Or using the scope operator :::
void MyHeader::SomeFunction(int Param)
{
// ...
}

The actual function is defined in the cpp file in a way that it does not implement the interface declared in the header file.
Implement
namespace MyHeader
{
void SomeFunction(int Param) { /* Your implementation goes here. */ }
}
in the cpp file.

Related

multiple definition error using namespace

I have created header file abc.hpp which contains a namespace of multiple functions.
When I use single source file which includes the header and call the function defined in namespace it works well, but when I call the same function in project where I have to include this header in multiple places, compilation gives me multiple definition error.
My other files are created as library and get executed.
abc.hpp:
#ifndef __ABC_HPP__
#define __ABC_HPP__
namespace abc {
void sendtext(const char* msg)
{
create_context(mycontext);
send_context(create_context,msg)
}
void sendtextwitherrno(const char* msg, int errn)
{
create_context(mycontext);
send_context(create_context,msg, errn)
}
};
#endif
test.cpp:
#include"abc.hpp"
int main()
{
abc::sendtext("hello world");
abc::sendtextwitherrno("hello error no",140);
return 0;
}
You can treat header files as if they are copy-pasted into your implementation files. So by putting function definitions into your headers, those definitions appear in multiple translation units (roughly, compiler .cpp files). This is not allowed - how is the compiler supposed to tell between them if they end up different?
Usually you would have a .h/.cpp pair, with function declarations going in the .h, and function definitions going in the .cpp. This way the definition only appears once in your whole program.
I can split your code like this:
abc.hpp:
#ifndef __ABC_HPP__
#define __ABC_HPP__
// function **declarations**
namespace abc{
void sendtext(const char* msg);
void sendtextwitherrno(const char* msg, int errn);
}
#endif
abc.cpp:
#include "abc.hpp"
#include "context.hpp" // I guess this might be where create_context and send_context come from
// function **definitions**
namespace abc{
void sendtext(const char* msg){
create_context(mycontext); // not sure where mycontext is supposed to live?
send_context(create_context,msg)
}
void sendtextwitherrno(const char* msg, int errn){
create_context(mycontext);
send_context(create_context,msg, errn);
}
}
test.cpp:
#include "abc.hpp"
int main(){
abc::sendtext("hello world");
abc::sendtextwitherrno("hello error no",140);
return 0;
}
Another way is to mark the functions as inline - this tells the compiler you are deliberately repeating the function definition all over the place, and you'd better be sure the definition is always identical. How sure are you? Are there different macros or different compiler flags in place in different places the function is used?

C++ global namespace members already defined error

I'm trying to make a namespace and its members available globally however I am running into already defined errors.
Settings.h
#pragma once
#include "boost/property_tree/json_parser.hpp"
#include <string>
using json = boost::property_tree::ptree;
namespace Settings {
extern std::string settingsPath;
extern json settings;
extern void init();
extern void readSettings();
extern void writeSettings();
};
Settings.cpp
#pragma once
#include "Settings.h"
using json = boost::property_tree::ptree;
namespace Settings {
void init() {
}
void readSettings() {
}
void writeSettings() {
}
};
I am forward declaring the Settings namespace and members and using extern. I have no idea what I'm doing wrong. Please could someone point out the error here.
Thanks
Edit: The actual error messages:
Error LNK2005 "class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > Settings::settingsPath" (?settingsPath#Settings##3V?$
basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A) already defined in
AmalgamService.obj Amalgam F:\Dropbox\CPP\Visual Studio Projects\Amalgam\Amalgam\
main.obj 1
And repeat for all members of the namespace. The Settings.h is #includeed in main.cpp and AmalgamService.cpp
You seem to be including Settings.cpp in another file. Do not include .cpp files. This results in duplicate definitions. This also means that #pragma once in .cpp files is useless.
You need to keep in mind that #include is just a glorified copy&paste tool. When you #include a file, that file is literally being copy&pasted into the spot of the #include statement. So including a .cpp file means you will get multiple definitions of everything defined in that .cpp file.
Furthermore, you don't have to use extern when declaring functions. Functions are extern by default, unless you say otherwise.
Variables are extern by default too, however you need to use extern as a way to declare them without defining them:
extern int var; // declaration
int var; // definition
Functions don't need that, because you can declare them by omitting their body:
void func(); // declaration
void func() { } // definition
You are allowed to declare things multiple times, which is why you can #include header files (like .h, .hpp) in multiple files. But you are not allowed to define things multiple times, which is why you can't #include non-header source files.

Linker error when including header in files other than main.cpp

I'm trying to add some utility functions and global variables to my code in such a way that I can be able to use them in every class I want in my project. I would like to use a .hpp file for the definitions end a .cpp file for the implementation.
This is a summary of these two files:
// This is Utilities.hpp
#ifndef utilities_hpp
#define utilities_hpp
namespace utils {
int global_variable1;
int global_variable2;
void utility_function1(...);
void utility_function2(...);
void utility_function3(...);
}
#endif /* utilities_hpp */
and the implementation:
// This is Utilities.cpp
#include "Utilities.hpp"
namespace utils {
void utility_function1(...) {
// Some code
}
void utility_function2(...) {
// Some code
}
void utility_function3(...) {
// Some code
}
}
Other than my main.cpp file I have two other classes. My main.cpp file includes Class1.hpp header that includes Class2.hpp header.
Now I thought that I could put another #include "Utilities.hpp" in Class1.hpp or Class2.hpp without any problems since I've used the guards in that header. The thing is that when I try to do that the linker throws me this error: Apple Mach-O Linker (ld) Error Group - clang: error: linker command failed with exit code 1 (use -v to see invocation) and I can't understand why or what to do to solve it.
I'm using Xcode 8.3 on a macOS Sierra 10.12.4.
I hope I was able to explain my problem, thank you all very much in advance.
You've violated the One Definition Rule. global_variable1 and global_variable2 should be declared extern in your header and defined in exactly one translation unit (probably Utilities.cpp).
You've defined global variables in a header that gets included in multiple translation units, so there's a utils::global_variable1 defined in main.cpp, and one in Utilities.cpp. When it comes to link time, the linker has no way to know which global_variable1 to use, so it throws an error.
To fix it, add the extern keyword to your declarations and add a definition in "Utilities.cpp":
Utilities.hpp:
// This is Utilities.hpp
#ifndef utilities_hpp
#define utilities_hpp
namespace utils {
extern int global_variable1;
//^^^^^^ <-----HERE
extern int global_variable2;
//^^^^^^ <-----HERE
void utility_function1(...);
void utility_function2(...);
void utility_function3(...);
}
#endif /* utilities_hpp */
Utilities.cpp:
// This is Utilities.cpp
#include "Utilities.hpp"
namespace utils {
int global_variable1; //<---- Definitions added
int global_variable2;
void utility_function1(...) {
// Some code
}
void utility_function2(...) {
// Some code
}
void utility_function3(...) {
// Some code
}
}
You're missing the extern keyword on your global variables in your header. As a result, you're defining them, which results in multiple definitions when you include the header in two different source modules.
Once you add the extern in the header file (extern int global_variable1;), you'll need to add the definition in your .cpp file where you also define your functions.

Declare and Define a Function in a Namespace?

I have the following header:
#ifndef MY_H_
#define MY_H_
namespace A {
void f() {
// do something
}
}
#endif
However, when I compiled, I got errors like multiple definition of A::f(). I thought that the #ifndef check is enough to avoid duplicate definitions in 1 translation unit. Maybe I miss something?
Thanks in advance.
Add inline specifier before the function definition:
#ifndef MY_H_
#define MY_H_
namespace A {
inline void f() {
// do something
}
}
#endif
You should declare functions in the header file but define them in your cpp file. If you include this header file from multiple translation units (which is most probable), then there will be multiple implementations available for different translation units. Each of your cpp files that includes this header will have an implementation of f. This way, if f is to be called, it is ambiguous. By putting the implementation into a cpp file, it can be linked and used that way. But there is only one implementation available which makes it unambiguous.
So, your header file should be:
#ifndef MY_H_
#define MY_H_
namespace A
{
void f(); // declaration only
}
#endif
and your source file:
#include "myHeader.h"
namespace A
{
void f()
{
// some implementation
}
}
Then, you should be fine. You would usually do that with all of your functions. The only exceptions are inline functions/methods or templates but this is beyond the scope of this question.

Why can't linker see my (definitely defined) externals?

I have a class with a header and a .cpp file. I declare my functions in the header, and define them in the .cpp file, as you would.
Header:
#pragma once
// my #includes
class CDNAGenerator
{
private:
// stuff
public:
CDNAGenerator(int, int);
~CDNAGenerator();
void FilterMeasurementsForOutliers(std::vector<double>& measurement_values);
// plenty more things
};
CPP:
CDNAGenerator::CDNAGenerator( int genes, int chromosomes )
{
// constructor code
}
void CDNAGenerator::FilterMeasurementsForOutliers(std::vector<double>& measurement_values)
{
// function code
}
Then, from a separate project in the same solution I reference the .h file (but not the .cpp - that seems to lead to multiple definition errors):
#include "..\CalibrationTool\DNAGenerator.h"
And call those functions:
CDNAGenerator* dnaGenerator = new CDNAGenerator(30, 0);
dnaGenerator->FilterMeasurementsForOutliers(values);
But I get unresolved external errors for CDNAGenerator::CDNAGenerator(int, int) and for CDNAGenerator::FilterMeasurementsForOutliers(class std::vector > &)
I thought that I had hooked everything up correctly, so can anyone suggest why I would be getting this linker error?
Add the CPP file to the project
What compiler are you using? Gcc (mingw) does'n supprort #pragma once Use code guards to avoid 'multiple definitions'.
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass {
...
}
#endif