C ++ Structures with different members - solved at runtime

I have the following situation. Below is the pseudo code. I have a class A that has an object c of type D or E, and that changes (in fact, a decision was made randomly). It uses b as a message to communicate with the remote computer.

  • So, how do I make structure B have different variables (float or double in this case)?
  • In addition, when I open the socket and pass the object, the object will now have a different size. The remote computer does not know if the object has a size corresponding to sizeof (int) + sizeof (float) OR sizeof (int) + sizeof (double). I need size as a parameter for receiving packets, so how can I solve this?

code:

class C { ... }; class D: public C { ... }; class E: public C { ... }; struct B { int a; // If A->c is of type D float b; // If A->c is of type E double b; }; class A { B b; C *c; A() { c = (C*) new D; //c = (C*) new E; } ... ... void transmit() { //b has some attributes depending on whether c is of type D or E //Open a socket and send packets via UDP //The remote host receives the packets } }; 

Hope this will explain my problem. If this is not clear or ambiguous, let me know. I will provide more detailed information and explanation. Thanks in advance.

+4
source share
5 answers

The union can be used to solve the problem.

 struct B { int a; bool d; //d = 0 for D and 1 for E union { float b; double c; } }; 
0
source

To create objects at run time, use the factory pattern .

Or use a template:

 template <class T> class A { T a; } A<int> a = new A<int>(); A<double> b = new A<double>(); 

The second part is simple.
In your send-receive protocol, keep 4 bytes at the beginning for sizeof (int) ... Then fill it with sizeof(a)

+2
source

Since both D and E follow from C, your implementation looks right:

 c = (C*) new D; 

Although I would remove C-Cast (this is not necessary, if you need throws, you should use C ++ variants).

 c = new D; 

How you transmit the data will depend. But usually you will need to prefix this piece of information with type information so that the receiver understands how to decode the next stream.

 send(a->a); send("1") if a->c is D send("2") if a->c is E send(<Conditional Part>); 

As a note. Look at smart pointers. Using a raw pointer in your class is a bad idea (and not good C ++).

+1
source

The work on Plain C ++ and the raw socket is really fussy, and many end up losing their structure through the socket, not thinking that other problems arise because of this.

  • You need to know about conversions with large and end users.
  • Not all compiler processes the structure as is. You often need to use the #pragma package to force a handle to the size of the structure. Some compilers do not support this.

If you're not worried about performance, I would recommend sending the data as XML / ini content, which is easy to parse. INI readers come with the convenience that you can read arguments like float or double.

If you still prefer binary content, I would recommend studying ASN.1 notations, but at least it will take you 2 weeks to fully practice your project, then you will stop using the existing protocol or use your own protocol.

Thus, there is no direct solution to your question. Instead of sending a copy of the structure to memory, you can ask your class C or D to send serialized data via a socket with the object type as the first byte, the data length in the next 2/4 bytes, the actual data for follow in rest order. Then you implement a reader class that reads the first byte, and then decides the type of object, and then delegates the call to the appropriate class to read the rest of the data.

+1
source

First of all, your class hierarchy looks suspicious. From what you showed, there is no connection between B and C , except for the existence of a third type, A , which contains the object B and the pointer C Still, the type of the variable inside B must depend on which subclass of C this pointer points to inside the object A ?

This seems like an unnecessary connection. Why not just include this field B in the corresponding subclasses of C ?

Assuming that you have corrected your class hierarchy, you still have a relatively straightforward problem with the need to send one of two different types of messages (different sizes) through the socket. Here is one solution:

 enum message_type {type1, type2}; class message_type1 { ... }; class message_type2 { ... }; // when sending message (pseudocode) write message_type variable write message_type1 object OR message_type2 object // when reading message (pseudocode) read message_type variable if type1 read message_type1 object else read message_type2 object 

Of course, message_type1 and message_type2 can be related, being subclasses of the same base class or instances of the same template, etc., to avoid repetition if the two types of messages have some common features.

EDIT . You mentioned in comments on other answers that you cannot split your message into different packages. Can you explain what this means? A “packet” is not an exact term: TCP has segments, UDP and IP have datagrams, and Ethernet has frames. None of them has any relation to how many times you call send() on a socket (i.e., two calls to send() ) do not necessarily mean that two TCP segments are sent, and vice versa, before send() does not guarantee that your data will be transferred in one segment).

+1
source

All Articles