Create a global array of objects in C++ - c++

I'm working on a drum pad to learn C++ programming.
I'm using a class called DrumSensor which I need to create 5 times in an array.
I'm using a header file "settings.h" to store variables I'll use throughout my code.
settings.h
extern DrumSensor sensor[5];
settings.cpp
#include "settings.h"
DrumSensor sensor[5];
I've been experiencing a lot with this global object array, but I've never been able to compile it.
I tried to find references such as:
Creating Array of Objects c++
c++ global object
The problem is, no matter how I try to declare my "DrumSensors", I get the following error:
... multiple definition of ...
You can take a look at the code here:
https://github.com/woodencase01/DrumSensor

About the code in your question
The way you have shown it is correct. You declared it in a header (and therefore, by extension, in any source file including that header), and defined it once in a source file.
You must be accidentally linking settings.cpp twice, or accidentally including settings.cpp somewhere, or you accidentally wrote another definition for this array somewhere.
About the code you pointed us to
FWIW, in the GitHub project you linked to, you do not have a settings.cpp, just a settings.h with loads of objects defined in it (i.e. without extern). So the problem may simply be that the code you are building is not the same code that you've been talking about.

Related

Linking files in C++

I'm trying to freshen up my basic C++ skills after a 2 year break by working on a basic card games program. So I created 3 objects: deck, hand, and card. Everything was working pretty well until I tried to define a global constant deck for the whole program to use and everything got screwed up (the deck is supposed to be all 52 cards in order and is never changed). I'm trying to figure out how to link the following files together:
main.cpp
deck.h
deck.cpp
hand.h
hand.cpp
card.h
card.cpp
Where do I need includes and also where and how do I define my global deck to be used across the program? I made a mess of my existing code to try to include everything in everything and now nothing is compiling correctly. Thanks!
For the deck, just define it in main.cpp. It can be passed by reference to any functions in other classes that would need to manipulate it. As far as headers, #include only the headers you need for the current source file. Including header guards is always a good idea as well, so you don't have to worry about how many times you reference a header.
EDIT
extern was mentioned in another answer. This is necessary if you're actually defining a global object. There are mixed opinions about globals. I've not seen it very often in pure C++.
To answer your question about the global you would declare it as extern in deck.h (I'm assuming that makes sense in your program) and define it in deck.cpp.
For instance:
deck.h
extern Card GLOBAL_DECK[52];
deck.cpp
Card GLOBAL_DECK[52];
Now as for using a global, it is a much better approach to avoid globals, and pass references to an object that lives in a higher scope, or create the object on the heap and pass pointers or references to it (but you have to remember to delete it once you are finished with it).
For the question about where do you need your includes, you should be wrapping each header in include guards like this (replacing HEADER_NAME with the header file name, for instance hand.h becomes HAND_H:
#ifndef HEADER_NAME
#define HEADER_NAME
header contents
#endif //Some people like to put HEADER_NAME here but it isn't really necessary
//unless you are using a lot of precompiler directives, which you shouldn't be
Then include the headers in files that need them. Hand and deck needs card, anything else depends on how you have used them. Since you haven't mentioned which complier/toolset you are using I can't give you specific instructions. But I would compile them by themselves and include what you need to get each file compiling. You may encounter circular dependencies, which means that A requires B to compile which requires A to compile (or a longer chain, but eventually it becomes circular), and you will need to research forward declarations and may need to use references and pointers to solve, or change your design.
Then you need to link the object files together to make an executable. If you are using an integrated IDE like Visual Studio or code::blocks it will do it for you, but you might need to find out what your linker is or set up one if you are using a generic IDE like eclipse.
Global variables (or constants) are declared at the top of a file, below the includes, but above any code.
So for this examples, I would write it simply like this :
#include <iostream>
#include <deck.h>
#include <hand.h>
#include <card.h>
extern deck ... // If we want to use the deck constant anywhere in our program
int main ()
{
...
}
notice that I assumed here that deck is non-constant (which I think would not pose a problem).
But if you absolutely need to use a global constant, you can create a new file, name it deckConstant.cpp for example then write the following in this file :
namespace myGlobalConstant
{
extern const deck ... // put the name of the constant you want
}
and create of course the file deckConstant.h :
#ifndef DECKCONSTANT_H
#define DECKCONSTANT_H
namespace myGlobalConstant
{
extern const deck ...
}
#endif
then in the main.cpp file you just add :
#include <deckConstant.h>
using namespace myGlobalConstant
I hope I understood the question right.

Different C++ Class Declarations

I'm trying to use a third party C++ library that isn't using namespaces and is causing symbol conflicts. The conflicting symbols are for classes my code isn't utilizing, so I was considering creating custom header files for the third party library where the class declarations only include the public members my code is using, leaving out any members that use the conflicting classes. Basically creating an interface.
I have three questions:
If the compilation to .obj files works, will this technique still cause symbol conflicts when I get to linking?
If that isn't a problem, will the varying class declarations cause problems when linking? For example, does the linker verify that the declaration of a class used by each .obj file has the same number of members?
If neither of those are a problem and I'm able to link the .obj files, will it cause problems when invoking methods? I don't know exactly how C++ works under the hood, but if it uses indexes to point to class methods, and those indexes were different from one .obj file to another, I'm guessing this approach would blow up at runtime.
In theory, you need identical declarations for this to work.
In practice, you will definitely need to make sure your declarations contain:
All the methods you use
All the virtual methods, used or not.
All the data members
You need all these in the right order of declaration too.
You might get away with faking the data members, but would need to make sure you put in stubs that had the same size.
If you do not do all this, you will not get the same object layout and even if a link works it will fail badly and quickly at run-time.
If you do this, it still seems risky to me and as a worst case may appear to work but have odd run time failures.
"if it uses indexes ": To some extent exactly how virtual functions work is implementation defined, but typically it does use an index into a virtual function table.
What you might be able to do is to:
Take the original headers
Keep the full declarations for the classes you use
Stub out the classes and declarations you do not use but are referenced by the ones you do.
Remove all the types not referenced at all.
For explanatory purposes a simplified explaination follows.
c++ allows you to use functions you declare. what you do is putting multiple definitions to a single declaration across multiple translation units. if you expose the class declaration in a header file your compiler sees this in each translation unit, that includes the header file.
Therefore your own class functions have to be defined exactly as they have been declared (same function names same arguments).
if the function is not called you are allowed not to define it, because the compiler doesn't know whether it might be defined in another translation unit.
Compilation causes label creation for each defined function(symbol) in the object code. On the other hand a unresolved label is created for each symbol that is referenced to (a call site, a variable use).
So if you follow this rules you should get to the point where your code compiles but fails to link. The linker is the tool that maps defined symbols from each translation-unit to symbol references.
If the object files that are linked together have multiple definitions to the same functions the linker is unable to create an exact match and therefore fails to link.
In practice you most likely want to provide a library and enjoy using your own classes without bothering what your user might define. In spite of the programmer taking extra care to put things into a namespace two users might still choose the same name for a namespace. This will lead to link failures, because the compiler exposed the symbols and is supposed to link them.
gcc has added an attribute to explicitly mark symbols, that should not be exposed to the linker. (called attribute hidden (see this SO question))
This makes it possible to have multiple definitions of a class with the same name.
In order for this to work across compilation units, you have to make sure class declarations are not exposed in an interface header as it could cause multiple unmatching declarations.
I recommend using a wrapper to encapsulate the third party library.
Wrapper.h
#ifndef WRAPPER_H_
#define WRAPPER_H_
#include <memory>
class third_party;
class Wrapper
{
public:
void wrappedFunction();
Wrapper();
private:
// A better choice would be a unique_ptr but g++ and clang++ failed to
// compile due to "incomplete type" which is the whole point
std::shared_ptr<third_party> wrapped;
};
#endif
Wrapper.cpp
#include "Wrapper.h"
#include <third_party.h>
void Wrapper::wrappedFunction()
{
wrapped->command();
}
Wrapper::Wrapper():wrapped{std::make_shared<third_party>()}
{
}
The reason why a unique_ptr doesn't work is explained here: std::unique_ptr with an incomplete type won't compile
You can move the entire library into a namespace by using a clever trick to do with imports. All the import directive does is copy the relevant code into the current "translation unit" (a fancy name for the current code). You can take advantage of this as so
I've borrowed heavily from another answer by user JohnB which was later deleted by him.
// my_thirdparty.h
namespace ThirdParty {
#include "thirdparty.h"
//... Include all the headers here that you need to use for thirdparty.
}
// my_thirdparty.cpp / .cc
namespace ThirdParty {
#include "thirdparty.cpp"
//... Put all .cpp files in here that are currently in your project
}
Finally, remove all the .cpp files in the third party library from your project. Only compile my_thirdparty.cpp.
Warning: If you include many library files from the single my_thirdparty.cpp this might introduce compiler issues due to interaction between the individual .cpp files. Things such as include namespace or bad define / include directives can cause this. Either resolve or create multiple my_thirdparty.cpp files, splitting the library between them.

Where to place STL / template code c++?

Hi I have what is hopefully a quick question. As part of homework I've been asked to write my own template vector class (most of the code is there it just needs to be expanded upon). While I understand HOW it works and WHAT it does I have no idea WHERE to put the code or reference it as I have never seen it in context within a program.
Do I create a new cpp file with all this information in it, or do I just add it in above my main method? If I create a new file (either cpp or h) how do I reference it, with just a #include like normal?
This might seem fairly simple but I've tried creating a new .h file and then including it in my main program but I always get scope definition errors.
Most compilers require you to put all the template code in a header file, rather than a source. This is due to the way template expansion works. You just include that header in whichever files need to use your vector class.
Some things to watch out for when creating a header:
Prevent multiple inclusion. If your compiler supports #pragma once you can put that at the top, otherwise use the #ifndef MY_HEADER_H ....... pattern.
Don't forget to put a semi-colon on the end of your class!!!!
Never put using namespace whatever; in the outer scope of a header (it's okay to use it within block scope such as namespace something { ... } or a function).
Be careful of name conflicts with std::vector if you are calling your class vector - make sure nobody has imported the std namespace prior to including your header.
One point you need to keep in mind is that you should place template declaration and definition together in the header file because of the compilation model of templates.
You can create a header file for the templated vector class and include this header file when you would like to use it in other .h or .cpp files.
You can also put them together inside main, but the previous option is better for you to maintain your code.

passing values between 2 different c++ files in same project

noob question right here. How do you pass values between 2 different cpp files in the same project? Do you make objects? if yes, how does the other cpp file see it?
some enlightment pls..
EDIT: some clarifications. I'm trying to interface direct input with a program (of which I have the plugins sdk). I'm trying to interface a joystick with it. It seems that there is no main function when I look through the code, but I might be wrong (like, I might not look in the right files). I know programming, and pointers and stuff, classes. Is there anything I should learn or get into in order to achieve what I want?
In all but few cases it's a bad idea to share data among compilation units. A compilation unit, just to get you up to speed with the C++ terminology, usually effectively refers to an implementation file (with extension .cpp, or .cc etc.). The way we have the various compilation units "communicate" with each other is with header files and functions, rather than raw data.
Suppose we have an implementation file main.cc and a second implementation file human.cc. We want main.cc to communicate with human.cc. Here we go:
// main.cc
#include "human.hh"
int main()
{
make_the_human_dance(60);
return 0;
}
// human.hh
void make_the_human_dance(int duration);
// human.cc
#include "human.hh"
void make_the_human_dance(int duration)
{
// define how a human dances properly
// ...
}
Under the same principle you can use classes for communication. Declare the class in the header file and define the class' methods in the implementation file. Sometimes you must provide the implementation of functions in the header files, but that is already going offtopic.
You could declare a global variable in a header file like so:
extern int GlobalVar;
And in exactly one compilation-unit (cpp-file) you have to initialize it:
int GlobalVar = 5;
Any other compilation unit that includes the header now shares the same instance of the global variable (I hope that syntax is correct, i rarely use it).
One should mention, that your question indicates a general lack of understanding of how programs in C++ should be organized. In short, you usually have a file called main.cpp that contains the entry-point of your program. The rest, in C++, is done in classes most of the time. A class is usually split into two parts, the declaration of the class in a header file, and the implementation of the class in a cpp file. To use a class, you include the corresponding header file. This is the short version, and there is much more to tell, but this should give you a good starting point.
Normally you define a function in one cpp file, then declare that function as extern in a header, and include the header in whatever other cpp file needs to use the function. You can then write code that calls the function normally. At link time you need to supply the object files that resulted from both cpp files, and the linker ...links them together, so the function call in one file passes the value correctly as you call the function that was defined in the other cpp file.
Referencing code in a different file typically makes use of #include

Global variables and scope - C++

I am having small problem in making a global variable works. I am using Visual Studio 2008 and standard C++.
I have two projects, one is a static library and second one is a test program which uses this library. I have a global variable in global.h like
#ifndef GLOBAL_H
#define GLOBAL_H
#include <string>
extern std::string globalWord;
#endif // GLOBAL_H!
I have a global.cpp where I am initializing this variable. This variable is used inside my library project. I am setting a value to this variable from the test project, but that value is not getting reflected in the library project.
I have debugged and it shows the new value in test project, but when the control reaches the library project, this variable value shows empty. So is this global variable's scope only limited to the project where it belongs to?
Or is there a better way to do this? I don't want to modify my function or constructor parameters in my library to pass this value.
Any help would be great.
Edit:
Here is how this variable is declared in global.cpp
#include <string>
#include "../global.h"
std::string globalWord = "";
This is how I used it in my library
#include "../global.h"
string text = globalWord;
Thanks
Don't use global variables. Just don't. Much better, if you HAVE to have globally accessible data, is to use a global function which will return globalWord, like this:
std::string globalWord()
{
static std::string word("Hi Mom");
return word;
}
This saves you from initialization order issues (read Effective C++ item #4).
With the "extern" keyword, you're telling the compiler that the actual variable exists somewhere else. You should also create a variable with the same name without the extern, in one and only one place. Ordinarily you'll get an error from the linker if you define two of them, but if one's in the library and one's not it might not figure it out.
Edit: make sure global.cpp is only in the library or test program, not both.
The problem is likely to be one of initialization order. When the program is linked, there are 2 places where globalWord is used in initialization:
in the initialization of text ("string text = globalWord;")
the initialization of globalWord itself
Unfortunately, the C++ standard does not specify the order of initialization of globals that come from different modules. Something similar to Matt's answer of using a function or a simple class (a singleton, for example) to access the global value is the usual way of enforcing a particular initialization order.
The C++ FAQ talks about this a little - if you plan to modify globalWord in your program, the situation is made a little more complex than they discuss because they don't seem to address setting the value hidden behind the "construct on first use" function. Typically something like that would require something like a singleton class.
The kind of behavior you describe seems more like a problem when you have a DLL, but you are saying that your library is static, which looks weird.
Anyway, take care with global variables in multiple libraries, if you have a shared code library (DLL) you'll get a value for each part. Check out this question, can be useful.