Reputation: 1266
I have a message class that I decided to use the builder design pattern. Each message, when completely built, looks very similar. I use a std::string
to hold the information (its actually just independent chars, so I could have used vector<char>
but the .c_str()
was convenient.
The method of construction of each different subtype of message is the same (build header, build cargo, build footer, calc checksum... this is defined in the MessageBuilder
class (and inherited to custom message builder classes):
class MessageBuilder
{
public:
// implementation details for all messages
static const int32 MsgDelimeter = 99;
// ...
Message getMsg();
void buildMessage();
protected:
MessageBuilder(uint8 msgID, uint8 cargoLen, uint8 csi, const uint8* cargo, const uint8 length)
: m_msgID(msgID), m_cargoLen(cargoLen), m_csi(csi),
m_cargo(cargo), m_contents(""), m_msg(m_contents)
{ }
// I previously tried passing cargo and length as just a std::string
// if I could get that to work it would also be fine
void buildHeader();
void buildCargo();
void buildFooter();
void resizeContents();
void calculateCheckSum();
// message is built in m_contents
Message::string m_contents;
Message::string m_cargo;
Message m_msg;
// variables specific to msg type
uint8 m_msgID;
uint8 m_cargoLen;
uint8 m_csi;
private:
};
Then to build a specific message, I have a specific class:
class CustomMessageABuilder : public MessageBuilder
{
public:
static const uint8 CustomMessageAID = 187;
// more details
// ...
// what I want to do
// static const uint8 CustomMessageACargo[4] = {0x65, 0xc7, 0xb4, 0x45};
// ** HERE **
CustomMessageABuilder ()
: MessageBuilder(CustomMessageAID,
CustomMessage1CargoLen,
//...
CustomMessageACargo,
CustomMessageALength
{ }
};
Anyway, what I want to do is pass the only custom string of characters, the cargo, from the CustomMessageABuilder
constructor to the MessageBuilder
class, where it will be stored in the middle of the message.
The cargo is different for each message, but gets stored in the same way, so all the logic for storing it/creating the cargo is in the base MessageBuilder
class. All the differences, like msgID, cargoLen, cargo, ... are constants in the CustomMessageBuilder
classes.
This would allow me to keep my message class really simple:
class Message
{
public:
typedef std::string string;
// ctor
Message(string);
// dtor
~Message();
// copy ctor
Message(const Message&);
// assignment operator
Message& operator=(const Message&);
// getters
uint8 getLength() const;
const string& getData() const;
const uint8* getCSTR() const;
// setters
void setData(const string&);
protected:
// ctor
Message() : m_contents("") { }
// contents of entire message
string m_contents;
};
So I guess it all boils down to this:
What is the best way to define a constant array of characters/hex values (each message cargo) for a class, (and still be able to pass it in the initialization list of the constructor)? Or, tell me the obvious way to do this that I am missing.
Note: For other message classes, the cargo will be dynamic content, but always fixed length.
Note2: I will eventually have a director class which will own a CustomMessageBuilder()
and tell it to buildMessage()
.
Any help, advice, criticism etc would be much appreciated.
Upvotes: 1
Views: 676
Reputation: 9410
Static const members can be initialized outside of the class.
#include <iostream>
class A
{
public:
static const char cargo[4];
};
const char A::cargo[4] = {0x65, 0xc7, 0xb4, 0x45};
int main()
{
std::cout << A::cargo[0] << A::cargo[1] << A::cargo[2] << A::cargo[3] << std::endl;
}
Upvotes: 1