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 have the below code giving me a syntax error on the BindingSocket definition, my understanding was if I wanted to define an inherited classes constructor I continue the BindingSocket definition with BindingSocket(...):Socket(...);, however this gives me a standard syntax error output.
#ifndef NETWORKING_BINDINGSOCKET_HPP_
#define NETWORKING_BINDINGSOCKET_HPP_
#include <stdio.h>
#include "Socket.hpp"
namespace HDE
{
class BindingSocket: public Socket
{
public:
BindingSocket(...) : Socket(...);
};
}
and then within my main cpp file I can write:
HDE::BindingSocket::BindingSocket(...): Socket(...)
{
Strangely enough if I add a {} at the end of the header definition for the class I get no syntax error.
The inheritance is given by class BindingSocket: public Socket.
The : Socket(...) after the constructor calls the parent constructor and belongs to the definition and not to the declaration.
So it has to be:
namespace HDE
{
class BindingSocket: public Socket
{
public:
BindingSocket(...);
};
}
And:
HDE::BindingSocket::BindingSocket(...): Socket(...)
{
I have two classes: SessionCardsMode and SetOfCards. SessionCardsMode takes in its constructor pointer to object of SetOfCards. When I try to create dynamically new SessionCardsMode object in SetOfCards method initializing it with this pointer I get information: "Cannot initialize type 'SessionCardsMode' with rvalue of type 'SetOfCards*'". It looks like I haven't proper constructor, but I have provided it. I don't know why it doesn't work. The problem is in SetOfCards::getSessionCards method in the first line of it. I've found that if I try to create the same object in body of class SessionCardsMode using identical statement everything works fine, but if I try to make it out of class I get the error.
//////////////////////////////SesionCardsMode.h
#pragma once
#include "Card.h"
#include "SetOfCards.h"
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
virtual Card* getCard();
//allows making combination of set setup by mixing classes that derives
//from ModeOfSet
void addAndShuffle(const SessionCardsMode* mode);
};
///////////////////////////////SetOfCards.h
#pragma once
#include "Card.h"
#include "SessionCardsMode.h"
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
template<typename Iter>
SetOfCards(Iter begin, Iter end, std::string setName);
SessionCardsMode* getSessionCards(std::vector<CreatorAndInitVal> creators);
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h"
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // error here
return sessionCards;
}
I don't understand why you don't get an error when you declare the constructor of SessionCardsMode (when you are compiling SetOfCards.cpp) - as far as I can see, at that point, SetOfCards is not defined.
Anyway, the solution to your problem is not to #include any of the headers in other headers, but to declare (not define) the other classes. So:
//////////////////////////////SesionCardsMode.h
#pragma once
class Card;
class SetOfCards;
class SessionCardsMode
{
protected:
SetOfCards* m_setData;
std::forward_list<Card*> m_sessionSet;
public:
explicit SessionCardsMode(SetOfCards* set) : m_setData(set) {};
...
};
///////////////////////////////SetOfCards.h
#pragma once
class Card;
class SessionCardsMode;
#include <vector> // You need this
#include <string>
class SetOfCards
{
private:
std::vector<Card> m_cardSet;
std::string m_setName;
public:
SetOfCards()=default;
explicit SetOfCards(std::string setName);
...
};
////////////////////////////////////////SetOfCards.cpp
#include "SetOfCards.h" // This should always be first
#include "..." // You'll probably need some more here.
SessionCardsMode* SetOfCards::getSessionCards(
std::vector<CreatorAndInitVal> m_sessionCardsCreators)
{
SessionCardsMode* sessionCards=new SessionCardsMode(this); // Error should be fixed
return sessionCards;
}
Forgive me, I'm a bit rusty with my C++.
I'm trying to create a Singleton via an interface (such that, the system can easily be expanded upon later as needed).
I've got the following interface:
#ifndef IBUILD_CONFIGURATION_H
#define IBUILD_CONFIGURATION_H
*IBuildConfiguration.h*
class IBuildConfiguration
{
public:
virtual int foo(void) = 0;
};
IBuildConfiguration& BCInstance(void);
#endif /* IBUILD_CONFIGURATION_H */
And the following concrete class:
BuildConfiguration.h
#ifndef BUILD_CONFIGURATION_H
#define BUILD_CONFIGURATION_H
class BuildConfiguration : public IBuildConfiguration
{
public:
BuildConfiguration();
~BuildConfiguration();
virtual int foo(void);
};
#endif /* BUILD_CONFIGURATION_H */
BuildConfigration.cpp
BuildConfiguration::BuildConfiguration()
{
// init stuff
}
BuildConfiguration::~BuildConfiguration()
{
// destroy stuff
}
int BuildConfiguration::foo(void)
{
return 382000; //just for fun
}
// Singleton initialization function
IBuildConfiguration& BCInstance(void)
{
static BuildConfiguration instance = BuildConfiguration();
return instance;
}
Now, I'm trying to use the object as follows:
MyClass.h
#include "IBuildConfiguration.h"
class MyClass
{
private:
IBuildConfiguration& oFoo;
public:
MyClass();
};
MyClass.cpp
MyClass::MyClass()
{
oFoo = BCInstance();
}
Unfortunately, this results in the compiler error 'oFoo' : must be initialized in constructor base/member initializer list and I can't figure out what's going on. Thanks
To add to what others have already indicated, the class members will already be created (through their default constructor) when the program enters the constructor body. Hence, any initialization within the class body will invoke the assignment constructor as the object would have already been created.
Now, since a reference cannot be re-initialzed, assigning a reference within the constructor body would mean re-initialization and hence the compiler flags an error asking you to initialize the reference in the constructor initialization list.
The same goes while initializing const members and members of class that do not have a default constructor.
Follow error message indication:
MyClass::MyClass() : oFoo(BCInstance())
{
}
You can't modify what a reference refers to. You can only initialize it:
MyClass::MyClass() : oFoo(BCInstance())
{
}
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.