Scope and Usage of Nested Classes - c++

I'm writing some code that interfaces with a GPS receiver and I'm trying to understand if the way I'm attempting to implement it is possible and if so how to do it.
The GPS communicates with an Arduino via I2C and I want to have a single object that handles all of the GPS interface commands. The basic structure is as follows:
Header File (Simplified)
//UBLOX.h
class UBLOX_INTERFACE
{
private:
const uint8_t i2cAddress;
public:
UBLOX_INTERFACE(uint8_t address);
class NMEA
{
private:
void intakeNMEA(); //This function needs access to UBLOX_INTERFACE::i2cAddress
//Other local variables and functions
};
class UBX_COMMS
{
private:
uint8_t prepAndSendPacket(uint8_t packet[], const uint16_t packetLength);
public:
UBX_COMMS(uint8_t ubxclass, uint8_t id, uint8_t length0, uint8_t length1);
};
class UBX_CFG_RATE : public UBX_COMMS
{
using UBX_COMMS::UBX_COMMS;
private:
public:
bool set(const uint16_t GNSSmeasureRate); // Sets GNSS measurement rate
void poll();
};
class UBX_CFG_RST : public UBX_COMMS
{
using UBX_COMMS::UBX_COMMS;
private:
public:
bool gnssReset(const uint8_t navBbrMask);
bool hardwareReset(const uint8_t resetMode);
};
}
CPP File (Simplified)
//UBLOX.cpp
#include "UBLOX.h"
//UBLOX_INTERFACE Class Functions
UBLOX_INTERFACE::UBLOX_INTERFACE(uint8_t address): i2cAddress(address)
{
NMEA nmea;
UBX_CFG_RATE ubxCFG_RATE(0x06, 0x08, 0, 6); //These values are permanently defined constants for each command type
UBX_CFG_RST ubxCFG_RST(0x06, 0x04, 0, 4);
}
//NMEA Class Functions
void UBLOX_INTERFACE::NMEA::intakeNMEA()
{
Wire.beginTransmission(i2cAddress); //This line has a compile error: invalid use of non-static data member 'UBLOX_INTERFACE::i2cAddress'
//There's a whole bunch more after this but not relevant to this question
}
//UBX_COMMS Class Functions
UBLOX_INTERFACE::UBX_COMMS::UBX_COMMS(uint8_t ubxclass, uint8_t id, uint8_t length0, uint8_t length1) : classByte(ubxclass), idByte(id), payloadLength{length0, length1}, stdPacketLength(packetLengthCalc(length0, length1)){};
uint8_t UBLOX_INTERFACE::UBX_COMMS::prepAndSendPacket(uint8_t packet[], const uint16_t packetLength)
{
calcAndInsertUBXChecksum(packet, packetLength);
Wire.beginTransmission(i2cAddress); //error: invalid use of non-static data member 'UBLOX_INTERFACE::i2cAddress'
Wire.write(packet, packetLength);
uint8_t errorCode = Wire.endTransmission();
return errorCode;
}
// UBX_CFG_RATE Class Functions
//definition of UBLOX_INTERFACE::UBX_CFG_PRT::setPort() and UBLOX_INTERFACE::UBX_CFG_PRT::poll()
// UBX_CFG_RST Class Functions
//definition of UBLOX_INTERFACE::UBX_CFG_RST::gnssReset() and UBLOX_INTERFACE::UBX_CFG_PRT::hardwareReset()
Example of how I want to use this
void main()
{
UBLOX_INTERFACE u;
u.ubxCFG_RST.hardwareReset();
u.ubxCFG_RATE.set(SOME SETTINGS HERE);
while(true)
{
u.nmea.intakeNMEA();
}
}
The real code I'm working with does not compile. Currently I'm getting errors in all of the subclasses where I attempt to use the UBLOX_INTERFACE::i2cAddress function: error: invalid use of non-static data member 'UBLOX_INTERFACE::i2cAddress' If I change the i2cAddress to be static, then I get a different error saying I have to use a non-static variable in the class construction. And on top of that, I'm unsure if my method of initializing the subclasses within the parent class constructor is even valid. Can anyone explain if this method is valid or what I should be doing instead?

You are trying to access i2cAddress from the class NMEA but you have defined the variable in the class UBLOX_INTERFACE.
The classes might be defined inside each other, but the instances of the classes does not have access to eachothers variable.
Alternatives would be to either make i2cAddress static, or global or to send a pointer or copy of i2cAddress or to UBLOX_INTERFACE to the class NMEA at some point.
Or depending on your code (i do understand it fully), you might want to put i2cAddress as a member variable of NMEA, that would also solve the problem.
Edit:
If you want to initialize a static member variable in the constructor, it is not possible to do it in the initializer list
//UBLOX_INTERFACE Class Functions
UBLOX_INTERFACE::UBLOX_INTERFACE(uint8_t address) // not here :
{
i2cAddress = address; // This should work
// The following variables does only exist in this function,
// I think that you might want to move these to the function body
// instead
NMEA nmea;
UBX_CFG_RATE ubxCFG_RATE(0x06, 0x08, 0, 6); //These values are permanently defined constants for each command type
UBX_CFG_RST ubxCFG_RST(0x06, 0x04, 0, 4);
}
And about if it would be possible to initialize like classes like you do: No I dont think it works like it does now. You need to add the classes as class members, and then initialize them in the initialize list like you previously did with i2cAddress.

Related

How to declare a class member that may be one of two classes

I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?
You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();

How to prevent a C++ compiler from creating any default class member?

I'm designing some classes to access and control the peripherals of a microcontroller (adc, port, usart etc). The device have just a few (in some cases just one) instances of each peripheral, so I decided to represent each peripheral as a monostate class. The definition and usage of one of my classes would be something like this:
usart.h
class usart {
public:
static void init() { /* initialize the peripheral */ }
static char read() { /* read a char from the input buffer */ }
static void write(char ch) { /* write a char to the output buffer */ }
// ... more member functions
};
main1.cpp
#include "usart.h"
int main()
{
usart::init();
char data;
while (true) {
data = usart::read();
usart::write(data);
}
}
But the way the usart class is defined above doesn't forbid the user from doing something like this:
main2.cpp
#include "usart.h"
int main()
{
// I don't want object construction
usart serial1;
usart serial2;
// neither assignment
serial1 = serial2;
// two objects representing the same hardware resource
// I don't want that
serial1.init();
serial2.write('r');
}
I know since C++11 I can use the delete keyword to prevent the compiler of creating default constructors and functions, but I don't know exactly what are those defaults the compiler creates. There are copy constructors, copy assigments, move semantics overloads etc. How many deletes I need to put on my class (and in what functions and constructors)?
update: I know I could (and maybe should) use namespaces instead of classes, but I'm afraid later I'll need to pass those classes (or namespaces) as template arguments. AFAIK it is not possible to use namespaces as template arguments, because of that I chose to use classes with static members instead of namespaces.
struct cannot_exist {
cannot_exist()=delete;
~cannot_exist()=delete;
cannot_exist(cannot_exist const&)=delete;
cannot_exist(cannot_exist &&)=delete;
cannot_exist& operator=(cannot_exist const&)=delete;
cannot_exist& operator=(cannot_exist &&)=delete;
};
this is a class with every member that C++ generates for you deleted explicitly. (You can do this with fewer, but I don't see the point being less explicit).
Simply inherit from cannot_exist and ... an instance of your class cannot exist, nor will it have any member function auto defined by the compiler. Attempts to call them will generate compiler errors.
However, once you have a class that cannot exist, consider using a namespace.
class usart:cannot_exist {
public:
static void init() { /* initialize the peripheral */ }
static char read() { /* read a char from the input buffer */ }
static void write(char ch) { /* write a char to the output buffer */ }
// ... more member functions
};
vs
namespace usart {
static void init() { /* initialize the peripheral */ }
static char read() { /* read a char from the input buffer */ }
static void write(char ch) { /* write a char to the output buffer */ }
// ... more member functions
};
I would try these two ways
Declare a pure virtual function in the class. This makes the class pure virtual so it cannot be instantiated.
Declare the default constructor as a private member function. This way no outside class method can access the constructor.

Error while trying to use boost::factory

I am trying to use boost factory and I am experiencing the following problem.
All I am trying to do is having a bunch of derived classes to have a mechanism that will be initializing the derived class that is matched with a corresponding string.
To begin with I have the following base class called name NetWorkBlock,
NetWorkBlock.h
class NetWorkBlock {
protected:
typedef boost::function<NetWorkBlock * ()> NetWorkFactory;
//definition of the function that will be used for the factory
public:
NetWorkBlock();
virtual ~NetWorkBlock();
//some basic functionalities that not related to the factory
and thus not mentioned
static std::map<std::string,NetWorkBlock::NetWorkFactory>& f_factory();
//static function that initializes and returns the map
};
NetWorkBlock.cpp
NetWorkBlock::NetWorkBlock() {
} //empty constructor
NetWorkBlock::~NetWorkBlock() {
} //empty deconstructor
std::map<std::string,NetWorkBlock::NetWorkFactory>& NetWorkBlock::f_factory()
{
static std::map<std::string,NetWorkBlock::NetWorkFactory>* ans =
new std::map<std::string,NetWorkBlock::NetWorkFactory>();
return *ans;
} //initialization of map
Moving on here is how I define things in the the derived class BusNetworkBlock (note ofcourse
there are more derived classes expected to be defined later, but in the current moment I work with a single derived class to manage to have things working):
BusNetworkBlock.h
class BusNetworkBlock {
public:
BusNetworkBlock();
virtual ~BusNetworkBlock();
//some basic functionalities that not related to the factory
and thus not mentioned
private:
/* Very small, "fake" class _initializer. Its only meaning is to define a
static member _init that is initialized at the very beginning of the
main(). Hence the constructor is called, and the constructor registers
the BusNetworkBlock class into the (static) NetWorkBlock::f_factory. */
static class _init {
public:
_init() {
NetWorkBlock::f_factory()["LoadCurve"] = boost::factory<BusNetworkBlock *>();
}
}_initializer;
};
BusNetworkBlock.cpp
BusNetworkBlock::BusNetworkBlock() {
} //empty constructor
BusNetworkBlock::~BusNetworkBlock() {
} //empty deconstructor
/* The definition of the bodies of the funcionalities of the class that are not mentioned here since they are not connected with the factory */
BusNetworkBlock::_init BusNetworkBlock::_initializer;
/* Ensure that the static member _initializer is initialized, so that
BusNetworkBlock is registered into NetWorkBlock::f_factory. */
Now in an other separate class under the name UCBlock I try to use the factory in order to initialize properly the derived NetworkBlock class based on a string I receive in the following way:
UCBlock.h
class UCBlock {
public:
UCBlock(std::istream& inStream); //the received instream
virtual ~UCBlock();
//some basic functionalities that not related to the factory
and thus not mentioned
NetWorkBlock * Network; /*defining a pointer of the base class NetWorkBlock
that want to initialize properly via the factory */
};
UCBlock.cpp
UCBlock::UCBlock( std::istream& inStream ) {
inStream >> network; //setting the string of network the corresponding factory
Network = NetWorkBlock::f_factory()[network](); // set the corresponding object via factory **here is where the problem arises**
}
And the problem arises when I try to use the factory to proper initialize the
derived class of NetWorkBlock. I receive the following error:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_function_call> >'
what(): call to empty boost::function
Aborted (core dumped)
Now I have ofcoruse tried to check this thing online but didn't manage to come up with a solution and that's why I would really appreciate any kind of help here, since I am really stacked here. (Note also that I checked that the string I receive is correct and matches with "LoadCurve").

Char array initialisation in class

I am trying to unit test a C++ application that I am building and I'm having an issue initializing the array when used in a class. I've tried alot of different methods of loading this information, the only ones that work are inefficient / not suitable.
Here is the hex array that I have (randomised the parts)
0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10
And header file for my unit test:
class MessageParsingTest : public CPPUNIT_NS::TestFixture {
CPPUNIT_TEST_SUITE(MessageParsingTest);
CPPUNIT_TEST(testIdentifyFirstMessageType);
CPPUNIT_TEST_SUITE_END();
public:
MessageParsingTest();
virtual ~MessageParsingTest();
void setUp();
void tearDown();
private:
void testIdentifyFirstMessageType();
void testIdentifySecondMessageType();
// data members for the hex array
unsigned char firstMessage[1500];
};
Then in my test case setUp function;
void MessageParsingTest::setUp() {
firstMessage = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
}
That it my latest failed attempt, it says its not valid during compilcation, as I expected, but at this point I was trying anything.
I've also tried things like (all in setUp function)
firstMessage << "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
firstMessage[1500] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
and a few other crazy ways, Does anyone know the proper way to load this data? the only way I've had it working so far is with either no data member declaration and straight up defining it and initializing in one line (but then I cant access in the test cases) or doing it one by one like firstMessage[0] = 0x24; etc.
I understand that there will be a simple, proper way of doing this and considering what the application actually does, this part should be the easiest.
You have few options:
Initialize arrays in constructor MesssageParsingTest using syntax : firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10}
in initializer list.
Create static const array containing your message, and either copy it to member variable using memcpy, or use static member and get rid of firstMessage member variable.
Declare const static member in .h inside class definition:
static const unsigned char kFirstMessage[];
and define + initialize it in .ccp
const unsigned char MessageParsingTest::kFirstMessage[] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
I would prefer static const member if you do not intend to modify this array later, since it makes the intention cleaner.
Here is one way to do it.
void MessageParsingTest::setUp()
{
unsigned char x[] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
::memcpy(firstMessage, x, sizeof(x));
}
If you are using C++11, you can also initialize the firstMessage in the class member initialization list as
MessageParsingTest::MessageParsingTest() :
firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10},
...
You can use a temporary buffer and then copy into you member as this:
void MessageParsingTest::setUp() {
unsigned char tmp[1500] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
memcpy(firstMessage, tmp, 1500);
}

"Stealth" class to enclose a variable in C++

I'm currently using two identical libraries for parsing commands received in Arduino (via TCP/IP and via Serial). All the difference is in the object type being passed to the parser.
//main.cpp
SerCmd sCmd;
EthCmd eCmd;
void setup() {
sCmd.listen("#",dumpCmd);
eCmd.listen("#",dumpCmd);
}
void loop() {
HardwareSerial SerClient = Serial.available();
EthernetClient EthClient = Server.available();
eCmd.read(SerClient);
sCmd.read(EthClient);
}
//SerCmd.h
class SerCmd {
public:
void read(HardwareSerial &dataObj);
}
//EthCmd.h
class EthCmd {
public:
void read(EthernetClient &dataObj);
}
It's obvious that:
The two objects are nearly identical, and they share lots of common methods (sCmd, eCd).
The two classes (SerCmd, EthCmd) can be replaced with a single class to reduce the sketch size.
How can I create a "stealth" class which could be passed to the read() method, while still addressing any of the two different objects underneath?
What's the common practice used in such situations?
So far, I am able to compile the below code, but cannot initialize any methods:
class Communication {};
HardwareSerial *SerClient;
Communication *Comm;
void setup() {
Comm = (Communication*) SerClient;
//Comm.begin(9600);
//Error: request for member 'print' in 'Comm',
//which is of non-class type 'Communication*'
}