gcc version 5.4.0 (GCC)
> g++ -std=c++11
During a build I get a multiply defined error message for a class constructor. When I delete the constructor, I get an undefined symbol error message. I'm stumped.
NodeClass::NodeClass( ... ) is marked as
Error Message:
build/Debug/Cygwin64-Windows/nodeClass.o: In function `__gnu_cxx::new_allocator<std::string*>::~new_allocator()':
/c/home/skidmarks/Projects/MPHASH/mphash/NodeClass.cpp:36: multiple definition of `NodeClass::NodeClass(std::vector<std::string*, std::allocator<std::string*> >&)'
build/Debug/Cygwin64-Windows/NodeClass.o:/c/home/skidmarks/Projects/MPHASH/mphash/NodeClass.cpp:36: first defined here
Header file:
# include <vector>
# include <gslip/SlipPointer.h>
class NodeClass : public SlipPointer
{
private:
vector<string*> vec;
public:
NodeClass(vector<string*>& vec);
virtual ~NodeClass() { };
private:
NodeClass(const NodeClass& orig) { };
};
Source Code:
# include <vector>
# include "NodeClass.h"
using namespace std;
using namespace slip;
NodeClass::NodeClass(vector<string*>& vec) :
SlipPointer(new string("Cluster Node")), vec(vec) {}
You have not provided sufficient info to confidently identify your compile error. I agree it is possible that a double definition might happen without sufficient and appropriate include guards. You have shown no include guards, and your error is not evident in the above code,
There are 2 types of include guards. I have seen both used, but less often at the same time. All are examples of conditional compile commands.
In the header file with name "NodeClass.h", my version of the header guard would have the first 2 and last line (examples of conditional compilation) of the following:
#ifndef NODECLASS_H // <--- header include guard
#define NODECLASS_H // <---
#include <vector>
#include <gslip/SlipPointer.h>
class NodeClass : public SlipPointer
{
private:
vector<string*> vec;
public:
NodeClass(vector<string*>& vec);
virtual ~NodeClass() { };
private:
NodeClass(const NodeClass& orig) { };
};
#endif // <---
In the code file, name "NodeClass.cc", my 2nd version of the header guard would include similar conditional compilation statements. This is less used in most environments, and I prefer the above.
#ifndef NODECLASS_H
#include "NodeClass.h"
#endif
#include <vector> // <-- redundant since also in header
using namespace std;
using namespace slip;
NodeClass::NodeClass(vector<string*>& vec)
: SlipPointer(new string("Cluster Node"))
, vec(vec)
{
}
I suspect you have out-of-line definitions of these functions in you header.
Initialization list is part of constructor's definition so you need to define it at the same place you define constructor's body. This means that you should have to do it in your header file:
NodeClass(vector<string*>& vec) :
SlipPointer(new string("Cluster Node")), vec(vec) {}
Since the definition of the constructor is not inline in the class definition, the compiler does not make it implicitly inline. Now, if you include the same file in multiple translation units (i.e. *.cpp files), the linker will produce exactly the error you see, because each of the *.cpp files will contain its own definition of the constructor without them being marked as inline functions.
Alternate easy solution is just to put a inline in front of the constructor declaration:
public:
inline NodeClass(vector<string*>& vec);
Related
I am currently working on a project where we have a shared set of headers. Now we want add some private fields without having to put those declarations directly in the shared headers.
Someone brought up the following:
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
Inside the _private.hpp headers we would then place the private fields for that class. When there are only default datatypes (int, bool, etc) this works fine(ish). But as soon as you put an include inside the _private.hpp file, for example #include everything breaks.
It is giving the following error expected unqualified-id before ‘namespace’ which as I understand is quite logical, since you're trying to define a namespace inside of a class.
Example _private.hpp file
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Now my question is, is there any way to trick the preprocessor, or somehow get the same results with a different solution?
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
If that code is including a file that looks like this:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Then you end up with this (though in reality, the #includes themselves would resolve to the contents of <string>, etc.):
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
};
}
Perhaps that shows your issue? You're including "string" in the middle of your class, but it needs to be included at the global namespace scope of your file.
Instead, include string at the top of the outer header, don't use include guards in the private header, and only put the body of the code you want pasted into your class into that private header. For that reason, you might not call it a ".hpp" file but something else to make it clear it's not a normal header.
Additionally, the __has_include feature seems dubious, because if your private header is missing you probably do not want it to compile to an empty class.
Worse, if you compile some translation unit that finds the header, and then compile another translation unit that does not find the private header, you will end up with two different definitions of your class, violating the One Definition Rule -- which is undefined behavior, no diagnostic required. Really nasty stuff (assuming your builds succeeds at all.)
I'm not a big fan of this kind of hiding, as it will make it hard for editors to properly show your code, to colorize and index your private header, or otherwise work with the code in a normal way. You might consider looking at the PIMPL idiom for hiding the implementation of a class in its .cpp file, so users of the header do not have to see it at all.
Can doSth() be inlined given this configuration?
// A.h
template<typename T>
struct A
{
void doSth();
};
// A.cpp
template<typename T>
void A<T>::doSth() { /* do something */ }
template class A<bool>;
template class A<int>;
// main.cpp
#include "A.h"
int main()
{
A<bool> a;
a.doSth();
}
If the answer is negative I'd go define my member functions in a .tpp file and include that at the end of "A.h" but that would just look weird with the non-inline versions in a .cpp file so I'd want to avoid that.
Most compilers cannot inline with that arrangement of code. The ICC compiler documentation claims it supports being invoked in a way that would enable that inlining AFTER you first built a different way, then gathered profiling data then fed back the profiling data to a cross module optimizing build. I made only modest attempts to get that to work and it worked only in play size projects, not in anything real.
For use with ordinary compilation, you should have that extra file for the function definitions you want inline, but you should probably not include it in the end of A.h, rather include A.h in the beginning of it and include it in select cpp files that really need it.
I prefer
// A.h
#ifndef A_H
#define A_H
template<typename T>
struct A
{
inline void doSth();
};
#endif
// A.tpp
#ifndef A_TPP
#define A_TPP
#include "A.h"
template<typename T>
inline void A<T>::doSth() { /* do something */ }
#endif
// Various other .h files that need to know what is declared in A
#include "A.h"
// Only cpp files that need what is defined in A.tpp
#include "A.tpp"
I forget the option as well as which compilers have such an option, but that nearly redundant use of inline in the .h file goes with a compiler option saying that in case the function is declared that way and used and not defined, throw a compile time error.
Without that option, the link time error is harder to read but does tell you which .cpp needed to include the .tpp but missed it.
You most definitely can. You also forgot the ; at the end of your struct definition.
struct a
{
// Whatever
};
Is how it should be.
Visual Studio does allow in-lining in this way but it limits the types that you can instantiate to just those that you defined in your A.cpp file.
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
I admit I'm a bit naive when it comes to includes. My understanding is that if you use it in your class you either need to include it or forward declare it. But then I was going through some code and I saw this:
// file: A.cpp
#include "Helper.h"
#include "B.h"
#include "C.h"
#include "A.h"
// ...
// file: A.h
B b;
C c;
// ...
// file: B.h
Helper h;
// ...
// file: C.h
Helper h;
// ...
Can someone explain to me why B and C does not need to include Helper? Also, what are the advantages/disadvantages to organizing includes this way? (Besides the obvious less typing.)
Thanks.
When you #include some header (or other) file into a .cpp file, that #include statement is simply replaced by the content of the header file. For example:
//header.h
int i;
float f;
// file.cpp
#include"header.h"
int main()
{}
After preprocessing stage, file.cpp will look like,
int i;
float f;
int main()
{}
Can see this in g++ using g++ -E file.cpp > TEMP, which shows you just the preprocessed files.
In your present question context, you must have #include helper.h in/before B.h and C.h as they appear before and you declare an object of those types.
Also, it's not good practice to rely on the arrangement of header files to get the code working, because once you alter arrangement little, the whole hierarchy collapses with several compilation errors.
Instead #include everything in the file if you are using it and you can use the #ifndef guards to avoid multiple inclusion:
//helper.h
#ifndef HELPER_H
#define HELPER_H
// content of helper file
#endif
If the class definitions for B and C don't actually refer to any of the members of the Helper class, then the compiler doesn't need to see the full definition of the Helper class in their header files. A forward declaration of the Helper class is sufficient.
For example, if the definition of the B class only uses pointers or references to Helper, then a forward reference is recommended :
class Helper;
class B {
// <SNIP>
Helper* helper;
// <SNIP>
void help(const Helper& helper);
// <SNIP>
};
If the definition of the B class uses an instance of the Helper class (ie. it needs to know the size of the Helper instance), or otherwise refers to the definition of the Helper class (in template functions eg.), then you need to make the full definition of the Helper class visible (most likely by including the header file that defines the Helper class) :
#include "helper.h"
class B {
// <SNIP>
Helper helper;
// <SNIP>
void help(Helper helper);
// <SNIP>
};
The rule of when to use includes versus forward declarations is relatively straightforward : use forward declarations when you can, and includes when you have to.
The advantage of this is clear : the less includes you have, the less dependencies there are between header files (and the more you'll speed up compilation).
Think of #include as literally including the text of the other file in this one - it's exactly the same as if you had copied it in. So in this case, the reason B and C don't need to include Helper is because you've included it in the same "compilation unit", which is what the combination of a .cpp file and all its includes is called.
With templates, a forward declaration might be enough even if the members of the forward declared type are referred to in the header file.
For example, the boost::shared_ptr<T> implementation only forward declares boost::weak_ptr<T> even though it is used in two constructors. Here is a code snipped from http://www.boost.org/doc/libs/1_47_0/boost/smart_ptr/shared_ptr.hpp:
namespace boost
{
// ...
template<class T> class weak_ptr;
// ...
template<class T> class shared_ptr
{
// ...
public:
// ...
template<class Y>
explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
{
// it is now safe to copy r.px, as pn(r.pn) did not throw
px = r.px;
}
template<class Y>
shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws
{
if( !pn.empty() )
{
px = r.px;
}
}
In this case, a forward declaration of boost::weak_ptr<T> is enough since the two constructors do not get instantiated unless the definition for the forward declared boost::weak_ptr<T> has been included in the compilation unit that is using those constructors.
Consider this code
#include <iostream>
#include <cstdio>
using namespace std;
class Dummy {
public:
Dummy();
};
inline Dummy::Dummy() {
printf("Wow! :Dummy rocks\n");
}
int main() {
Dummy d;
}
All is good here!
Now I do this modification. I move the declaration of Dummy to "dummy.h".
class Dummy {
public:
Dummy();
};
And define the constructor Dummy() as following in "dummy.cpp"
#include "dummy.h"
inline Dummy::Dummy() {
printf("Wow! :Dummy rocks\n");
}
And finally, I have my main file as:
#include <iostream>
#include <cstdio>
#include "dummy.h"
using namespace std;
int main() {
Dummy d;
}
It compiles fine, but I get a linker error complaining an undefined reference to Dummy::Dummy().
Any insights.
--
You have to put all inline functions (including methods and constructors/destructors) in a header file, where they are declared.
Though this code should work either way, with main() calling the constructor as if the inline keyword was not there. Are you sure you are passing object files from both compilation units to the linker?
You should think how compiling works at C++ and the idea of separate compiling units used at C++ and encapsulation gained using headers and cpp files.
Look here:
http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.6
The inline tells the complier that instead of calling the function to "copy - paste" its code at the place of the function call. When you put the inline definition in a CPP file it won't be visible during linking to other compiled units (its in cpp file not in h file) so the compiler understand from the signature placed at the class that there is no-paramter Con's so it won't implement the default one. But the linker can't find the function body cause it is implemnted inline at the cpp file.
Try removing the inline specifier from the your implementation file. If my understanding is correct, you can only inline in a header