How to pass constant arrays to constructor initializer lists - c++

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.

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;
}

Related

Parsing custom data packets in an object oriented manner

I am currently developing some software in C++ where I am sending and receiving custom data packets. I want to parse and manage these packets in a well structured manner. Obviously I am first receiving the header and after that the body of the data. The main problem is that I don't like creating a Packet-Object with only the header information and later on adding the body data. What is an elegant way of parsing and storing custom data packets?
Here is a rough sketch of what such a custom data packet could look like:
+-------+---------+---------+----------+------+
| Magic | Command | Options | Bodysize | Body |
+-------+---------+---------+----------+------+
(Lets assume Magic is 4 bytes, Command 1 byte, Options 2 bytes, Bodysize 4 bytes and the body itself is variable in length.)
How would I parse this without using any third party libraries?
Normally I'd say something like this could be done to store packet data:
#include <array>
class Packet {
public:
explicit Packet(std::array<char, 10> headerbytes);
void set_body(std::vector<char> data);
std::vector<char> get_body();
int8_t get_command();
int16_t get_options();
bool is_valid();
private:
bool valid;
int8_t _command;
int16_t _options;
int32_t body_size;
std::vector<char> _data;
};
The problem is that I provide the header-information first and than add the body data in a hacky way later on. The packet object has a point of time where it is accessible in an incomplete state.
I first receive the header and after the header was received another receive call is made to read the body.
Would it make sense to have a parser instance that populates information into the packet object only make it accessible once it holds all needed information? Would it make sense to have a separate class for the header and the body? What would be the best design choice?
I am developing with C++ and for the sending and receiving of data over sockets the boost library is used.
If you don’t want to tie the data reading into one complete constructor (for understandable reasons of separation of concerns), this is a good application for non-polymorphic inheritance:
struct Header {
static constexpr SIZE=10;
Header(std::array<char,SIZE>);
std::int8_t get_command() const {return command;}
std::int16_t get_options() const {return options;}
std::int32_t body_size() const {return length;}
private:
std::int8_t command;
std::int16_t options;
std::int32_t length;
};
struct Packet : private Header {
using Body=std::vector<char>;
Packet(const Header &h,Body b) : Header(h),body(std::move(b))
{if(body.size()!=body_size()) throw …;}
using Header::get_command;
using Header::get_options;
const Body& get_body() const {return body;}
private:
Body body;
};
// For some suitable Stream class:
Header read1(Stream &s)
{return {s.read<Header::SIZE>()};}
Packet read2(const Header &h,Stream &s)
{return {h,s.read(h.body_size())};}
Packet read(Stream &s)
{return read2(read1(s),s);}
Note that the private inheritance prevents undefined behavior from deleting a Packet via a Header*, as well as the surely-unintended
const Packet p=read(s);
const Packet q=read2(p,s); // same header?!
Composition would of course work as well, but might result in more adapter code in a full implementation.
If you were really optimizing, you could make a HeaderOnly without the body size and derive Header and Packet from that.
For this case I would use the pipeline design pattern creating 3 packet processor classes:
Command (handles magic bytes too)
Options
Body (handles body size too)
all derived from one base class.
typedef unsigned char byte;
namespace Packet
{
namespace Processor
{
namespace Field
{
class Item
{
public:
/// Returns true when the field was fully processed, false otherwise.
virtual bool operator () (const byte*& begin, const byte* const end) = 0;
};
class Command: public Item
{
public:
virtual bool operator () (const byte*& begin, const byte* const end);
};
class Options: public Item
{
public:
virtual bool operator () (const byte*& begin, const byte* const end);
};
class Body: public Item
{
public:
virtual bool operator () (const byte*& begin, const byte* const end);
};
}
class Manager
{
public:
/// Called every time new data is received
void operator () (const byte* begin, const byte* const end)
{
while((*fields[index])(begin, end))
{
incrementIndex();
}
}
protected:
void incrementIndex();
Field::Command command;
Field::Options options;
Field::Body body;
Field::Item* const fields[3] = { &command, &options, &body };
byte index;
};
}
}
You can use exceptions to prevent creation of incomplete packet objects.
I'd use char pointers instead of vectors for performance.
// not intended to be inherited
class Packet final {
public:
Packet(const char* data, unsigned int data_len) {
if(data_len < header_len) {
throw std::invalid_argument("data too small");
}
const char* dataIter = data;
if(!check_validity(dataIter)) {
throw std::invalid_argument("invalid magic word");
}
dataIter += sizeof(magic);
memcpy(&command, dataIter, sizeof(command)); // can use cast & assignment, too
dataIter += sizeof(command);
memcpy(&options, dataIter, sizeof(options)); // can use cast & assignment, too
dataIter += sizeof(options);
memcpy(&body_size, dataIter, sizeof(body_size)); // can use cast & assignment, too
dataIter += sizeof(body_size);
if( data_len < body_size+header_len) {
throw std::invalid_argument("data body too small");
}
body = new char[body_size];
memcpy(body, dataIter, body_size);
}
~Packet() {
delete[] body;
}
int8_t get_command() const {
return command;
}
int16_t get_options() const {
return options;
}
int32_t get_body_size() const {
return body_size;
}
const char* get_body() const {
return body;
}
private:
// assumes len enough, may add param in_len for robustness
static bool check_validity(const char* in_magic) {
return ( 0 == memcmp(magic, in_magic, sizeof(magic)) );
}
constexpr static char magic[] = {'a','b','c','d'};
int8_t command;
int16_t options;
int32_t body_size;
char* body;
constexpr static unsigned int header_len = sizeof(magic) + sizeof(command)
+ sizeof(options) + sizeof(body_size);
};
Note: this is my first post in SO, so please let me know if something's wrong with the post, thanks.
I'm guessing you are trying Object-oriented networking. If so, the best solution for such parsing would be Flatbuffers or Cap’n Proto C++ code generator. By defining a schema, you will get state machine code that will parse the packets in an efficient and safe way.

Unique_Ptr: Attemting To Reference A Deleted Function

So I'm working on a school project right now in C++, although I'm not too familiar with the language yet.
The whole project is divided in several Milestones.
1: Reading a list with different Types of Creatures and storing them in a vector
2: Reading a TGA-File and storing it in a class.
...
5: Reading a TGA-Picture for every read Creature-Type and storing it for further use. (Printing on GUI, Remove/add)
So I thought it is a good idea to store the picture for each type in the class itself, as it should only be loaded once.
The load() function in my TGAPicture class will return std::unique_ptr so I added the type as an argument in my CreatureType class.
After doing that, I got several error like this:
Error C2280 'biosim::CreatureType::CreatureType(const biosim::CreatureType &)': attempting to reference a deleted function bio-sim-qt E:\Development\C++\bio-sim-qt\bio-sim-qt\qtmain.cpp 58 1
Error (active) function "biosim::CreatureType::CreatureType(const biosim::CreatureType &)" (declared implicitly) cannot be referenced -- it is a deleted function bio-sim-qt e:\Development\C++\bio-sim-qt\bio-sim-qt\Model.cpp 15 26
So I read about 10 questions with similar titles like mine and every one pointed out, that you cant copy unique_ptr and suggested solutions like using std::move() or returning a reference.
Although I tried to use these to fix my problem, I wasn't able to do it in the slightest, probably because I'm pretty new to C++ and have never worked with unique pointers.
This is the code, that seems relevant to me:
/**
* #class CreatureType
* Object of the various CreatureTypes ingame
*/
class CreatureType {
private:
std::string name;
int strengh;
int speed;
int lifespan;
std::vector<std::string> attributes;
std::string path;
std::unique_ptr<TGAPicture> picture; //What I tried to add in order to stre my pictures
public:
CreatureType(const std::string& name
, int strengh, int speed, int lifespan
, const std::vector<std::string>& basic_strings
, const std::string& path);
/**
* Initializes list with CreatureTypes by reading from a .txt-File
*/
static CreatureList load(const std::string& file);
/**
* Printing Data in various ways
*/
void getInfo() const;
void getInfoInOneLine() const;
std::string getName() const;
int getStrengh() const;
int getSpeed() const;
int getLifespan() const;
std::vector<std::string> getAttributes() const;
std::string getPath() const;
};
}
CreatureType::CreatureType(const std::string& name
, int strengh, int speed, int lifespan
, const std::vector<std::string>& basic_strings
, const std::string& path)
: name(name),
strengh(strengh),
speed(speed),
lifespan(lifespan),
attributes(basic_strings),
path(path),
picture(TGAPicture::loadPicture(Reference::PicturePath::creatureBasePath + path)){ }
/**
* Implementation Notes:
* - Does a line not fullfill the requirenments, it will be ignored
* - #see Formation
* - Prints data with std::cout
*/
CreatureList CreatureType::load(const std::string& file) {
CreatureList creatureList;
std::ifstream fileStream; //Datei-Handle
int lineNumber = 0;
int correctLinesRead = 0;
fileStream.open(file, std::ios::in);
if (!fileStream.is_open()) {
throw FileNotFoundException(file);
}
logger << INFO << "Einlesevorgang wird gestartet\n";
//One line per loop
while (!fileStream.eof()) {
bool skipLine = false;
std::string line;
getline(fileStream, line);
lineNumber++;
... //Checking if data is valid
//Every Parameter does exist and is valid
creatureList.push_back(CreatureType(creatureArgs[0]
, strengh, speed, lifespan
, attributes, creatureArgs[5]));
correctLinesRead++;
}
return creatureList;
}
TGAPicture:
//no padding bytes
#pragma pack( push, 1 )
/**
* #struct TGAHeader
* Represents the standard TGA-Header.
*/
struct TGAHeader {
char idLength;
char colourmapType;
char imagetype;
short colourmapStart;
short colourmapLength;
char colourmapBits;
short xOrigin;
short yOrigin;
short width;
short height;
char bits;
char descriptor;
};
#pragma pack( pop )
/**
* #struct RGBA
* Represents a Pixel with a red, green, blue and possibly alpha value
*/
struct RGBA {
std::uint8_t B, G, R, A;
};
/**
* #class TGAPicture
* Class used to represent TGA-Files, that are used in the program
*/
class TGAPicture {
public:
TGAPicture(const TGAPicture& other)
: pixel(other.pixel),
header(other.header),
width(other.width),
height(other.height),
size(other.size),
bitsPerPixel(other.bitsPerPixel) {}
TGAPicture(TGAPicture&& other) noexcept
: pixel(std::move(other.pixel)),
header(std::move(other.header)),
width(other.width),
height(other.height),
size(other.size),
bitsPerPixel(other.bitsPerPixel) {}
TGAPicture& operator=(const TGAPicture& other) {
if (this == &other)
return *this;
pixel = other.pixel;
header = other.header;
width = other.width;
height = other.height;
size = other.size;
bitsPerPixel = other.bitsPerPixel;
return *this;
}
TGAPicture& operator=(TGAPicture&& other) noexcept {
if (this == &other)
return *this;
pixel = std::move(other.pixel);
header = std::move(other.header);
width = other.width;
height = other.height;
size = other.size;
bitsPerPixel = other.bitsPerPixel;
return *this;
}
private:
std::vector<RGBA> pixel; //Containes every pixel of the picture
TGAHeader header;
short width, height, size, bitsPerPixel;
...
public:
/**
* Loads and initializes a picture to be used in the program
* #throws TGAExpection if file could not be loaded
*/
static std::unique_ptr<TGAPicture> loadPicture(const std::string& path);
TGAPicture(const std::vector<RGBA>& pixel, const TGAHeader& header);
~TGAPicture();
....
};
}
#endif
cpp:
TGAPicture::TGAPicture(const std::vector<RGBA>& pixel, const TGAHeader& header)
: pixel(pixel),
header(header),
width(header.width),
height(header.height),
size(header.width * header.height * (header.bits / 8)),
bitsPerPixel(header.bits) { }
std::unique_ptr<TGAPicture> TGAPicture::loadPicture(const std::string& path) {
...
for (int i = 0; i < header.height * header.width; i++) {
pixel[i].B = *(bufferPosition++);
pixel[i].G = *(bufferPosition++);
pixel[i].R = *(bufferPosition++);
pixel[i].A = (header.bits > 24 ? *(bufferPosition++) : 0xFF);
}
/**
* Return unique_ptr
* - ObjectFactory
* - Automatic Deletion
*/
return std::unique_ptr<TGAPicture>{new TGAPicture(pixel, header)};
}
And one class with an error would be:
class Model {
public:
explicit Model(const CreatureList& creatureList);
~Model();
Terrain* getTerrain() const;
CreatureList& getCreatureList();
private:
CreatureList creatureList;
Terrain* terrain;
};
Model::Model(const CreatureList& creatureList) : creatureList(creatureList),
terrain(new Terrain()) {
for (CreatureType ty : creatureList) { //line with errror
ty.getInfoInOneLine();
}
}
What do I need to change for it to work? And what would be the optimal way? Pretty sure that I'm supposed to use unique_ptr as return for the TGA::load() method.
I hope you can see through this mess and I'd like to apologize if my English isn't perfect, since it's not my first langugage.
std::unique_ptr is not copyable. It wouldn't be unique anymore if you could copy it.
You create copies of the elements in creatureList in your loop in Model's constructor, but they have a non-copyable member, and so are non-copyable themselves by default. If you don't actually need a copy of the elements, you should use references:
Model::Model(const CreatureList& creatureList)
: creatureList(creatureList),
terrain(new Terrain())
{
for (CreatureType& ty : creatureList) { // changed to reference instead
// Note: this is still working with
// parameter, not the object's
// member.
ty.getInfoInOneLine();
}
}
You haven't actually provided a definition for CreatureList, but I suspect it also isn't copyable. This means that Model::Model's argument can't be copied into the object's member. You have two options to fix this: make sure to move your CreatureList or make it copyable.
std::unique_ptr is movable, which means that CreatureType is by default as well, so you can do something like this:
Model::Model(CreatureList creatureList) // Take by value now
: creatureList(std::move(creatureList)), // Move the parameter to the member
terrain(new Terrain())
{
for (CreatureType& ty : this->creatureList) { // Use this-> to access member
// instead of now moved-from
// parameter. You could also
// just change them to have
// different names.
ty.getInfoInOneLine();
}
}
This changes Model's constructor to take its parameter by value and moves that value into the object's creatureList member.
If it makes sense, you could also make CreatureType copyable by adding an explicit copy constructor that copys the object pointed to by picture:
CreatureType::CreatureType(const CreatureType& other)
: name(other.name),
strengh(other.strengh),
speed(other.speed),
lifespan(other.lifespan),
attributes(other.attributes),
path(other.path),
picture(new TGAPicture(*other.picture))
{
}
If you do that, the implicit move constructor will no longer be generated by the compiler, so you'll want to define that yourself:
CreatureType::CreatureType(CreatureType&& other)
: name(std::move(other.name)),
strengh(other.strengh),
speed(other.speed),
lifespan(other.lifespan),
attributes(std::move(other.attributes)),
path(std::move(other.path)),
picture(std::move(other.picture))
{
}
There doesn't seem to be any reason for TGAPicture::loadPicture to return a std::unique_ptr though. If you just return by value from that function you will avoid all of these problems:
TGAPicture TGAPicture::loadPicture(const std::string& path) {
// ...
return TGAPicture{pixel, header};
}

Should C++ classes contain or be constructed/populated from protocol buffer messages

For protocol buffers in C++, I am wondering if it is better to contain a protobuf message in my class, or to have it be constructed from and populate an external protobuf message.
I could not find examples describing best practices for this case. I'm particular worried about performance differences between the two designs.
In my processing, I will have some cases where I am going to read only a few fields from my message and then route the message to another process (possibly manipulating the message before sendind it back out), and other cases where my objects will have a long lifetime and be used many times before being serialized again. In the first case, I could likely operate directly on the protobuf message and not even need my class, execpt to fit into an existing interface.
Here is an example message:
package example;
message Example {
optional string name = 1;
optional uint32 source = 2;
optional uint32 destination = 3;
optional uint32 value_1 = 4;
optional uint32 value_2 = 5;
optional uint32 value_3 = 6;
}
I could see one of the following designs for my class. I know these classes aren't doing anything else but accessing data, but that's not what I'm trying to focus on for this question.
Composition
class Widget
{
public:
Widget() : message_() {}
Widget(const example::Example& other_message)
: message_(other_message) {}
const example::Example& getMessage() const
{ return message_; }
void populateMessage(example::Example& message) const
{ message = message_; }
// Some example inspectors filled out...
std::string getName() const
{ return message_.name(); }
uint32_t getSource() const;
{ return message_.source(); }
uint32_t getDestination() const;
uint32_t getValue1() const;
uint32_t getValue2() const;
uint32_t getValue3() const;
// Some example mutators filled out...
void setName(const std::string& new_name)
{ message_.set_name(new_name); }
void setSource(uint32_t new_source);
{ message_.set_source(new_source); }
void setDestination(uint32_t new_destination);
void setValue1(uint32_t new_value);
void setValue2(uint32_t new_value);
void setValue3(uint32_t new_value);
private:
example::Example message_;
};
Standard data members
class Widget
{
public:
Widget();
Widget(const example::Example& other_message)
: name_(other_message.name()),
source_(other_message.source()),
destination_(other_message.destination()),
value_1_(other_messsage.value_1()),
value_2_(other_messsage.value_2()),
value_3_(other_messsage.value_3())
{}
example::Example getMessage() const
{
example::Example message;
populateMessage(message);
return message;
}
void populateMessage(example::Example& message) const
{
message.set_name(name_);
message.set_source(source_);
message.set_value_1(value_1_);
message.set_value_2(value_2_);
message.set_value_3(value_3_);
}
// Some example inspectors filled out...
std::string getName() const
{ return name_; }
uint32_t getSource() const;
{ return source_; }
uint32_t getDestination() const;
uint32_t getValue1() const;
uint32_t getValue2() const;
uint32_t getValue3() const;
// Some example mutators filled out...
void setName(const std::string& new_name)
{ name_ = new_name; }
void setSource(uint32_t new_source);
{ source_ = new_source; }
void setDestination(uint32_t new_destination);
void setValue1(uint32_t new_value);
void setValue2(uint32_t new_value);
void setValue3(uint32_t new_value);
private:
std::string name_;
uint32_t source_;
uint32_t destination_;
uint32_t value_1_;
uint32_t value_2_;
uint32_t value_3_;
};
There is no recognized "best practice" here. I have seen plenty of examples of both, and even written programs that worked both ways. Some people have very strong opinions about this, but in my opinion it depends on the use case. For example, as you say, if you plan to forward most of the data to another server, then it makes a lot of sense to keep the protobuf object around. But other times you have a more convenient internal representation -- for example, before protobufs added native support for maps, if you had a protobuf that represented a map as a repeated list of key/value pairs, you might want to convert it to an std::map upfront.

Initialize static object graph

I want to create a number of objects that hold constant data for an application.
I have got the following code until now:
class NodeObject;
class ComplexData
{
struct datum
{
Type type;
int value;
};
vector<datum> data;
vector<NodeObject*> nodeObjects;
public:
void addDatum(Type, int) const;
void addNodeObject(NodeObject*) const;
};
class NodeObject
{
int id;
string name;
ComplexData complexData;
NodeObject(string); // private
public:
static const NodeObject NODE_1;
static const NodeObject NODE_2;
static const NodeObject NODE_3;
};
const NodeObject NodeObject::NODE_1("Node 1");
const NodeObject NodeObject::NODE_2("Node 2");
const NodeObject NodeObject::NODE_3("Node 3");
However I'm not sure, how to put the more complex data into my nodes while keeping the single nodes constant. I think, I could drop the const keyword since members are private, but that doesn't really solve the problems. At the moment I use this very ugly aproach - I hope there are better ways to do so:
class NodeObject
{
// stuff like before ...
private:
static bool initialized;
static bool initialize();
};
bool NodeObject::initialize() {
// for example
NODE_1.complexData.addDatum(someType, 1);
NODE_3.complexData.addNodeObject(&NODE_1);
}
bool NodeObject::initialized = NodeObject::initialize();
Due to the fact that I don't need the bool variable afterwards I think it can be eliminated somehow.? Putting everything into the constructor might be possible but that will blow up the code too much.
Do ye have any suggestions?

Use singleton classes in c++

I created a singleton class
class AreaDataRepository {
private:
AreaDataRepository();
AreaDataRepository(const AreaDataRepository& orig);
virtual ~AreaDataRepository();
Way onGoingWay;
public:
static AreaDataRepository& Instance()
{
static AreaDataRepository singleton;
return singleton;
}
void SetOnGoingWay(Way onGoingWay);
Way const & GetOnGoingWay() const;
};
void AreaDataRepository::SetOnGoingWay(Way onGoingWay) {
this->onGoingWay = onGoingWay;
}
Way const & AreaDataRepository::GetOnGoingWay() const {
return onGoingWay;
}
header file of Way
class Way {
private:
std::string id;
std::string name;
public:
Way();
Way(const Way& orig);
virtual ~Way();
void SetName(std::string name);
std::string const & GetName() const;
void SetId(std::string id);
std::string const & GetId() const;
};
Then i'm created a Way object and set vales of id and name.
Way wayNode;
wayNode.SetId("123");
wayNode.SetName("jan")
AreaDataRepository::Instance().SetOnGoingWay(wayNode);
After assign OngoingWay accessing it from another class.
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId();
the vale is not printing.
I'm going psychic here.... and I divine that your implementation of SetId is like this:
void SetId(std::string id) { id = id; }
that does not set the member variable, that sets the parameter to itself. And since your constructor most likely set the member variable id to "" you're printing empty strings. Either change the name of the parameter (to newId for example) to avoid the conflict or change the implementation to:
void SetId(std::string id) { this->id = id; }
As proof of this claim here's the result for the first version, as you see it prints nothing. And here is the result for the second, as you can see it prints the number.
The problem boils down to this: you have function parameter names that are the same as the name of your member variables and the function parameters are shadowing/hiding the member variables.
The only place this cannot happen is in a constructor's initialization list:
class Foo {
int x;
public:
Foo(int x): x(x) {} // <-- this works
void SetX(int x) { x = x; } // <-- this won't the parameter is hiding the member variable
};
Demo for the above snippet
std::cout is buffered in most implementations, if not in all. That means, the stream will wait for you to end a line before writing out any data. So, you can easily fix this by changing your output statement to
std::cout << AreaDataRepository::Instance().GetOnGoingWay().GetId() << std::endl;