I am working on a project for my job to encode/decode into buffers DNS Records objects in C++. Some records have the same infos, so I created a class Dns message with theses basic infos:
class CDnsMessage
{
public:
CDnsMessage();
virtual ~CDnsMessage();
virtual int GetSize() = 0;
uint32_t m_ttl;
DnsClass dclass;
DnsType type;
std::string m_domain;
};
The DnsClass
and DnsTypes
are enum with the differents class/types I use. Then I have my sub-classes for each record, I will take A for the example:
class CDns_RR_A : public CDnsMessage
{
public:
CDns_RR_A();
virtual ~CDns_RR_A();
virtual int GetSize(CDnsMessage const& msg);
uint32_t m_address;
};
Then I have my encode/decode function in another header, encoder.h
and encoder.cpp
.
I am receiving a DnsMessage
(the object) and receiving buffer, and I encode or decode. So I used dynamic cast to know which type of record it is, and adapt the encode and decode to the variables the object has.
here is my decode for example:
EncodeResult DecodeData(const char * buffer,CDnsMessage & msg,std::size_t size)
{
EncodeResult res(ENCODE_OK);
uint32 ttl = 0;
eDnsClass dnsclass;
eDnsType dnstype;
//decoding RR_A
if(CDns_RR_A* RR_A_msg = dynamic_cast< CDns_RR_A* >( &msg ))
{
uint32_t address;
dnsclass = CLASS_IN;
msg.dclass = dnsclass;
dnstype = TYPE_A;
msg.type = dnstype;
res = DecodeInt32(&buffer,&size,&ttl);
CHECK_DECODE_ERROR(res);
msg.m_ttl = ttl;
res = DecodeInt32(&buffer,&size,&address);
CHECK_DECODE_ERROR(res);
msg.m_address = address;
}
}
The DecodeInt32
is a function made by people before long time ago, it takes a buffer (char**
), a size_t*
and a uint32
.
I have two problems, first I can’t access the members of my subclass, when I compile I got a problem with msg.dclass or msg.type and It says “request for member ‘class’ in ‘RR_A_msg’, which is of non-class type ‘CDns_RR_A*’ but I don’t understand, if my dynamic cast works it mean that the msg received waiting to be fulfilled is of type A no?
And my second problem is: I am using uint32_t
for the ttl (imposed by enterprise) and my decodeint32
takes uint32
so the compiler says invalid conversion from uint32_t* to uint32
.
Is there away to convert one to another?
Edit: Updated my code following answers and advices, now i have
if(dynamic_cast< CDns_RR_A* >( &msg ) != nullptr)
{
CDns_RR_A* RR_A_msg = dynamic_cast< CDns_RR_A* >( &msg )
uint32 address;
dnsclass = CLASS_IN;
RR_A_msg->dclass = dnsclass;
dnstype = TYPE_A;
RR_A_msg->type = dnstype;
res = DecodeInt32(&buffer,&size,&ttl);
CHECK_DECODE_ERROR(res);
RR_A_msg->m_ttl = ttl;
res = DecodeInt32(&buffer,&size,&address);
CHECK_DECODE_ERROR(res);
RR_A_msg->m_address = address;
}
Changing uint32_t to uint32 for decode worked, and having RR_A_msg-> instead of msg. worked too.
But now i have undefined reference to
typeinfo for CDns_RR_A’`
Advertisement
Answer
For the “you cannot convert uint32_t* to uint32” the issue is that the former is a pointer and the later is not. You should take the & off the front and pass the value not a pointer to it.
I don’t know why you can’t get the class member (maybe related to using a reserved name as a variable?) but you shouldn’t be able to access m_address in this way.
Instead of
msg.m_address
You need to be using
RR_A_msg->m_address