I know there is a initailzer trick to forcing a global object to be constructed regardless of where it is used. This is used for std::cout i believe.
#ifndef GUARD_H
#define GUARD_H
class Magical
{
// default constructor and such...
};
class Init
{
public:
Init();
};
extern Magical& magic;
namespace
{
Init __magical_initializer; // works as this object is constructed in every source file it is included in
}
#endif
src:
#include "magical.h"
#include <new>
static int count; // believe there is a spec somewhere which states global integers are initialized with zero
static alignas(Magical) char buffer[sizeof(Magical)];
Magical& magic = *reinterpret_cast<Magical*>(buffer);
Init::Init()
{
if(!count++)
{
new(buffer) Magical;
}
}
I was wondering if there was a template equivalent to this, as such my code would look something like this:
template<typename T>
class Base
{
static Magical<T> __private; // need this constructor to be called.
};
// usage:
class SomeClass : public Base<SomeClass>
{
};
No way to solve this problem as templates can't exist in source files.
Related
I have a class Dmx with a nested class touchSlider. So before I had these classes in my main.cpp file and just created an object array of touchSlider within the Dmx class and it worked properly. How can I implement this here, with different header files? The compiler gives an error message: invalid use of incomplete type 'class Dmx::touchSlider' The object array is: touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};
dmx.h
// dmx.h
#ifndef dmx_h
#define dmx_h
class Dmx {
public:
byte number;
Dmx(byte numberA) {
number = numberA;
}
void settingsDisplay();
class touchSlider; // declaration of nested class
touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};
};
#endif
touchSlider.h
// touchSlider.h
#ifndef touchSlider_h
#define touchSlider_h
#include "dmx.h"
class Dmx::touchSlider{
private:
int pos;
public:
touchSlider(int posA){
pos = posA;
}
void printChannel();
};
#endif
main.cpp
// main.cpp
#include "dmx.h"
#include "touchSlider.h"
Dmx dmx[10] = {Dmx(1), Dmx(2),Dmx(3), Dmx(4), Dmx(5), Dmx(6), Dmx(7), Dmx(8), Dmx(9), Dmx(10)};
void Dmx::settingsDisplay() {
// do something
}
void Dmx::touchSlider::printChannel() {
// do something
}
My previous code (that worked great) where both classes where in the same file looked like this:
class Dmx {
public:
byte number;
Dmx(byte numberA) {
number = numberA;
}
void channelDisplay(){
}
void settingsDisplay(){
}
class touchSlider{
private:
int pos;
public:
touchSlider(int posA){
pos = posA;
}
void setChannel(/* some arguments*/){
}
void printChannel();
}
};
touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};
};
Dmx dmx[10] = {Dmx(1), Dmx(2),Dmx(3), Dmx(4), Dmx(5), Dmx(6), Dmx(7), Dmx(8), Dmx(9), Dmx(10)};
To be able to create an array:
touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};
You need the class definition available, because the compiler needs to know
the size of the struct or class in use and
if there's a suitable constructor available.
You now have two options, either you provide the class definition in the header but implement the class within the source file like:
// header:
class Dmx
{
public:
// ...
class TouchSlider
{
public:
// only DECLARE here:
TouchSlider(int posA);
void setChannel(/* some arguments*/);
void printChannel();
};
};
// source:
Dmx::TouchSlider::TouchSlider(int posA)
: pos(posA) // note: prefer the initialiser list!
{ }
void Dmx::TouchSlider::setChannel(/* some arguments*/)
{
}
// ...
or you hide away the implementation as you intended, but then you need to allocate the memory dynamically (this is the PImpl idiom) – at best with help of a std::unique_ptr:
class Dmx
{
public:
// ...
private:
class TouchSlider; // just declare
std::unique_ptr<TouchSlider[]> sliders;
};
Important (see cppreference), though:
std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the pImpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr.
I.e. you cannot implement e.g. your class' destructor in the header file either but need to do so in the source file as well – after the nested class' full definition – alike any function that might re-assign another array.
The std::unique_ptr avoids necessity of manual memory management (see rules of three/five), on the other hand the class gets non-copiable (but you can work around by providing your own custom copy constructor and assignment while defaulting the move constructor and assignment).
In order to create an array of touchSlider the compiler needs a definition of the touchSlider class. So as written this will not work.
In the code given
touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};
the complier needs to know how big a touchSlider object is so it can allocate enough memory for a Dmx object. It also needs to know that a touchSlider can be constructed from an int. Both these things require the full definition of touchSlider.
Now maybe you can use some variation to achieve whatever your goal is, but without more details it's hard to suggest anything.
I checked several answers on the forums about this topic, but for some reason I still cannot wrap my mind about the problem and get my works running.
My aim is to have one object of a class available in all translation units. Note, I do not seek to implement a singleton pattern here. There can be multiple instances of the class, but there will always be at least one and this one can be seen where "its header" is included.
Assume a design like this:
---logging.h---
class LogCenter {
...
}
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
}
The reason? I want that all Loggers can use this global LogCenter per default, wherever they may be used.
But now I'm unsure how to provide this global LogCenter. It has the default constructor. Do I just add a line extern LogCenter globalCenter; into the logging.h file and another LogCenter globalCenter; line into the logging.cpp file? Or just LogCenter globalCenter; in the logging.cpp and extern LogCenter globalCenter; in any file that uses it?
I am really confused, none of which I tried worked - however, the overall code works fine when I use the constructor overload with its own LogCenter instance.
EDIT: Important: extern goes with declaration (e.g. in header file). Then one single definition in an implementation file.
Check all the answers!
This is how it works:
---logging.h---
class Entry;
class LogCenter {
friend class Logger; //please don't bash my friend design right away... D:
private:
list<Entry> entries;
public:
void printLog(string file);
}
extern LogCenter SCenter;
class Logger {
private:
LogCenter& center;
public:
Logger(); //uses extern or "singleton" object.
Logger(LogCenter&);
void commitEntry(Entry); //adds the Entry object to the list in the center object.
}
-----------------
---logging.cpp---
#include "logging.h"
LogCenter SCenter;
void Logger::commitEntry(Entry e) {
entries.push_back(e); //Logger can access LogCenter fields!
}
void LogCenter::printLog(string file) {
//open file stream str
for(list<Entry>::iterator it = entries.begin();...)
str << it->getEntry() << endl;
//close file
}
--------------
---main.cpp---
#include "logging.h"
int main() {
Logger log;
Entry e("Some entry");
log.commitEntry(e);
SCenter.printLog("filename.log");
//or
LogCenter cent;
Logger log(cent);
Entry e("some entry");
log.commitEntry(e);
cent.printLog("filename.log");
return 0;
}
-------------
Using an extern variable is one option.
Another option is to have a function that returns a reference.
logging.h:
LogCenter& getGlobalLogCenter();
logging.cpp:
LogCenter& getGlobalLogCenter()
{
static LogCenter lc;
return lc;
}
//logcenter.h
#ifndef LOGCENTER_H_
#define LOGCENTER_H_
class LogCenter {
private:
int dummy;
public:
int getVal(){ return dummy; };
LogCenter() : dummy(0){};
LogCenter(int val) : dummy(val) {};
};
#endif // LOGCENTER_H_
xxx
// logcenter.cpp
#include "LogCenter.h"
LogCenter globalCenter;
xxx
//logger.h
#ifndef LOGGER_H_
#define LOGGER_H_
#include <string>
#include "LogCenter.h"
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
std::string print() { return std::string("This class uses logger ") + std::to_string(center.getVal()); };
};
#endif // LOGCENTER_H
xxx
// logger.cpp
#include "Logger.h"
extern LogCenter globalCenter;
Logger::Logger() : center(globalCenter) {};
Logger::Logger(LogCenter &logcenter) : center(logcenter) {};
xxx
// main.cpp
#include "Logger.h"
int main(int argc, char* argv[])
{
LogCenter logcenter2(2), logcenter3(3);
Logger logger1, logger2(logcenter2), logger3(logcenter3);
std::cout << logger1.print() << std::endl;
std::cout << logger2.print() << std::endl;
std::cout << logger3.print() << std::endl;
return 0;
}
output is:
This class uses logger 0
This class uses logger 2
This class uses logger 3
I recommend you to use the following C++ singleton pattern which is easy to use and even safe when using it across shared libraries:
// LogCenter.h
class /*API_MACRO_FOR_EXPORTING*/ LogCenter {
public:
static LogCenter* instance();
}
// For quick access you could define a macro
#define sLogCenter \
LogCenter::instance()
// LogCenter.cpp
LogCenter* LogCenter::instance()
{
static LogCenter instance;
return &instance;
}
// LogCenter::instance()->DoSomething();
// sLogCenter->DoSomething();
To answer your question about extern:
// LogCenter.h
// You can use multiple definitions with extern so the compiler
// knows the LogCenter is instantiated somewhere else.
extern LogCenter globalCenter;
// LogCenter.cpp
// Only 1 declaration of LogCenter
/*API_MACRO_FOR_EXPORTING*/ LogCenter globalCenter;
I would go with the second option, that is, "extern LogCenter globalCenter;" in the file where ever it is used.
The reason, if someone is including logging.h, may be for creating the new object of Logcenter class, but does not intend to use the globalCenter object, then why he needs the extern declaration for globalCenter object.
I have an issue when trying to initialize static members of a static class template.
Basically, what I thought this approach would be useful for:
I have a lot of objects, which are of course all of the same Base type but they have differing object types. I just want to manipulate these objects, that's why I decided to use a static template as there are quite a number of different types these object can consist of.
However, for logging and options passing I wanted to add the corresponding members to the template whithout having to write initializers for every derived static class.
Please note that the following code is not actually working, because there is some SDK involved.
I'm just aksing for the right approach, not right code.
Thanks in advance. :)
template.h:
#ifndef _TEMPLATE_H
#define _TEMPLATE_H
#include "stats.h"
template<class T>
class TemplateObj
{
public:
static void SetParameters(const Options& options)
{
T::_options = options; // Is this even possible?
T::Init();
T::DoStuff(_options);
}
protected:
static void Message() { stats.Print("Message from Template static method"); }
static Stats& TemplateObj<T>::stats = Stats::GetInstance(); // This will not work as this is a non-trivial initializer, how to do it correctly? Stats::GetInstance() retrieves a singleton instance
static Options& TemplateObj<T>::_options; // Possible?
};
#endif
derived.h:
#ifndef _DERIVED_H
#define _DERIVED_H
#include "template.h"
class Derived :TemplateObj < Derived >
{
public:
static void Init();
static void DoStuff(Options& options)
};
#endif
derived.cpp:
#include "derived.h"
void Derived::Init()
{
// Init stuff here
TemplateObj::Message(); // Call static method from template directly
}
void Derived::DoStuff(Options& options)
{
// Do something with options
stats.Print("Message from derived static method."); // Access to "stats" here. "stats" should be declared and initialized inside the template.
options.Load(); // Example
}
main.h
#include "derived.h"
main()
{
TemplateObj<Derived>::SetParameters(new Options);
}
Basically, you don't need to put TemplateObj<T>:: before the function definition if it is inside the class definition. The following two are both valid:
template<class T>
class A{
void func( void );
};
template<class T>
void A<T>::func() { /* Okay */ }
template<class T>
class B {
void func( void ){ /* Okay */ }
};
In your case, replace the following static Stats& TemplateObj<T>::stats = Stats::GetInstance(); with static Stats& stat() { return Stats::GetInstance(); }
And the following static Options& TemplateObj<T>::_options; with this static Options& _options;.
On the other hand, replace this T::_options = options; with TemplateObj<T>::_options = options;.
Trying to pass a parent class object to a child class object so that the child class object has control over the parent class object's methods.
This is however resulting in header related issues.
I've tried forward declaring one of the classes but it seems whatever class is declared first always has trouble reading from the class declared below.
Both errors refer to Device' constructor where try to call dm's hello world method, they are:
Use of undefined type 'DeviceManager'
Left of '->HelloWorld' must point to class/struct/union/generic type
...
//main.cpp
#include "parent.h"
void main()
{
cout << "Created DeviceManager\n";
DeviceManager* deviceManager = 0;
deviceManager = new DeviceManager;
cout << "Giving DeviceManager a device\n";
deviceManager->p = new Device(deviceManager);
cout << "Giving Device a reference to DevicenManager\n";
deviceManager->Share();
}
...
class DeviceManager;
class Device
{
public:
Device(DeviceManager* manager)
{
dm = 0;
this->dm = manager;
this->dm->HelloWorld();
}
DeviceManager* dm;
};
//device manager
class DeviceManager
{
public:
DeviceManager()
{
p = 0;
}
void HelloWorld()
{
//if this calls we know the child has control over the parent.
cout << "Hello World";
}
Device* p;
};
Yes.
To solve circular dependencies with class member and function declarations, you can forward-declare a class:
class A;
class B {
A *a;
};
class A {
B *b;
};
To define class member functions that access members of the other class, you must define the function after the other class has been defined:
class B;
class A {
public:
void f(B &arg);
};
class B {
public:
void g(A &arg);
};
void A::f(B &arg) {
arg.g(*this);
}
void B::g(A &arg) {
arg.f(*this);
}
Usually, in a C++ project, you wouldn't even encounter this problem: You would put function definitions, i.e. implementations, into .cpp files, while putting the class definitions into header files. Class forward declarations, if neccesary, could be put into their own header files that are included by all headers that need them.
A full example of how you would split the above code into multiple files:
a.cpp
#include "a.h"
#include "b.h"
void A::f(B &arg) {
arg.g(*this);
}
b.cpp
#include "b.h"
#include "a.h"
void B::g(A &arg) {
arg.f(*this);
}
a.h
#ifndef _A_H_
#define _A_H_
#include "forward_declarations.h"
class A {
public:
void f(B &arg);
};
#endif //_A_H_
b.h
#ifndef _B_H_
#define _B_H_
#include "forward_declarations.h"
class B {
public:
void g(A &arg);
};
#endif //_B_H_
forward_declarations.h
#ifndef _FORWARD_DECLARATIONS_H_
#define _FORWARD_DECLARATIONS_H_
class A;
class B;
#endif //_FORWARD_DECLARATIONS_H_
As a general rule of thumb, if you need to forward-declare a class, you might have misdesigned something and should think about whether there is a better way (but there also are perfectly valid use cases that require class forward declarations).
If you don't understand my #ifndef, #define and #endif preprocessor lines: These are header guards, and should be used with all files that are included somewhere else, exception you know precisely what you're doing. Believe me. You'll regret ommiting one.
If your problem is cyclic dependancy, like this:
// DeviceManager.h
#include "device.h"
class DeviceManager
{
DeviceManager(Device& device) {}
};
// Device.h
#include "DeviceManager.h"
class Device
{
Device(DeviceManager& manager) {}
};
You can solve the problem be forward declaring one of the classes, and passing the object by pointer.
// Device.h
//#include "DeviceManager.h"
class DeviceManager;
class Device
{
Device(DeviceManager* manager) {}
};
In my class I have the need to keep a pointer to a structure which is defined in a library I use to implement it. Since this library is only used within the implementation file I would like to avoid including it in the header directly. At the same time I want to avoid polluting the namespace. Thus I would like to do:
/* HEADER */
class Foo {
private:
struct ImplementationDetail;
ImplementationDetail * p;
};
/* SOURCE */
#include <Library.h>
using Foo::ImplementationDetail = Library::SomeStruct;
But this doesn't work, and I'm currently falling back on PIMPL:
/* HEADER */
class Foo {
private:
struct ImplementationDetail;
ImplementationDetail * p_;
};
/* SOURCE */
#include <Library.h>
struct ImplementationDetail {
Library::SomeStruct * realp_;
}
Is there a way to avoid the double dereference? Is the reason for my non-working first solution due to unknown pointer sizes?
// Header
class Foo {
private:
struct ImplementationDetail;
ImplementationDetail * p;
};
// Source
#include <Library.h>
struct Foo::ImplementationDetail :public Library::SomeStruct {
// ....
};
and allocating/deallocating/dereferencing the pointer in this source file only should work just fine.
This is an incorrect declaration:
using Foo::ImplementationDetail = Library::SomeStruct;
using doesn't work this way. In C++11 using cannot create an alias for a name in one namespace to a name in another namespace. In C++03, all using does is bring some other namespace in to global visibility in the current translation unit. It's not used to create aliases in C++03, as you seem to want to do here.
pimpl is the de-facto method for doing what you're trying to do, but in your header file instead of trying to use a ImplementationDetail*, I would use a simple void*. Using a void* in this manner is guaranteed to be correct according to the Standard:
class Foo {
private:
void * pImpl;
Use static_cast2 to go from a void* to your actual type:
void Foo::Bar()
{
Library::SomeStruct* thingy = static_cast <Library::SomeStruct*> (pImpl);
// ...
}
You can avoid using the void* in a conformant way by forward-declaring your library type:
namespace Library
{
struct SomeStruct;
};
class Foo
{
private:
Library::SomeStruct* pStruct;
};
And then no ugly cast is needed in the implementation.
2 Use static_cast : Or reinterpret_cast
The reason you can't take your first approach is that in the header you tell the compiler "I'm declaring a nested class within Foo and it's called ImplementationDetail". Then you proceed to say "wait wait, it's NOT a new class, it's an alias to this other thing entirely" and understandably the compiler gets confused.
Have you tried just forward declaring the library's implementation and using that instead of trying to create an alias?
In your first code you declared the nested type ImplementationDetail to be a struct which will be define inside Foo. Trying to alias it can't work because that would be a type defined elsewhere and, actually, you private structure isn't accessible from outside the class. Wrapping a pointer to another object inside seems unecessary: you could instead either embed the Library::SomeStruct by value or have your ImplementationDetail derive from Library::SomeStruct:
struct ImplementationDetail
: Library::SomeStruct {
using Library::SomeStruct::SomeStruct;
};
(the using declaration is just used to inherit all the constructors from Library::SomeStruct).
I think this is not possible without casting.
Basically there are two ways to do it:
1) Define p_ as void* and cast it in every function that uses it.
/* HEADER */
class Foo {
private:
void* p;
};
/* SOURCE */
#include <Library.h>
void Foo::AnyFunc()
{
Library::SomeStruct* pImpl = reinterpret_cast<Library::SomeStruct*>(p);
...
}
2) Create a "shadowing"-class of your class (in the .cpp-file) with all members cloned and p_ defined as Library::SomeStruct. Then cast the this-pointer to this shadowing class. This is of course a quite insecure and dirty hack which I don't recommend...
/* HEADER */
class Foo {
private:
void* p;
};
/* SOURCE */
#include <Library.h>
class FooImpl
{
public:
void AnyFunc() { p->DoSomething(); }
private:
Library::SomeStruct* p;
}
void Foo::AnyFunc()
{
FooImpl* pImpl = reinterpret_cast<FooImpl*>(this);
pImpl->AnyFunc();
}
This exploits memory structure and is therefore quite fragile (all members need to be in the same order and when you add or remove members, you need to update ShadowFoo, too). I mentioned this just for completeness.
3) This brings us to yet another, but more simple way: create the implementation in the source file and initialize it in the constructor with the void*-pointer:
/* HEADER */
class Foo {
private:
void* p;
};
/* SOURCE */
#include <Library.h>
class FooImpl
{
public:
FooImpl(void* pSomeStruct)
{
p = reinterpret_cast<Library::SomeStruct*>(pSomeStruct);
}
void AnyFunc() { p->DoSomething(); }
private:
Library::SomeStruct* p;
}
void Foo::AnyFunc()
{
FooImpl impl = FooImpl(p);
impl.AnyFunc();
}