实施细节 [英] implementation details

查看:64
本文介绍了实施细节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设new_command的返回值是MSG2_STATUS


我的意图是通过调用CMDHolder来记忆数据和

有一个函数''将检索''存储''数据的副本。

后者我不确定该怎么做。任何有用的帮助。

#include< iostream>

#include< map>

using namespace std;


int msg2_status_index = 0;

int msg1_status_index = 0;

int msg1_cmd_index = 0;


MSG2_STATUS _msg2_stat [2]; //用于双缓冲

MSG1_STATUS _msg1_stat [2]; //用于双缓冲

MSG1_CMD _msg1_cmd [2]; //用于双缓冲


typedef enum

{

_msg1_cmd = 0,

_msg1_status ,

_msg2_status

} MSG_ID;


typedef struct //这是++。为什么要使用typedef。 ''详情''我想'

{

MSG_ID来源;

unsigned int msg_length:12;

unsigned int count:4;

} MSG_HEADER;


typedef struct _MSG2_STATUS

{

MSG_HEADER header ;

unsigned int idx:1;

unsigned int jdx:3;

unsigned int kdx:4;

unsigned int spare:24;

unsigned int ldx:32;

} MSG2_STATUS;


typedef struct _MSG1_STATUS

{

MSG_HEADER标题;

unsigned int idx:1;

unsigned int jdx:3;

unsigned int kdx:4;

unsigned int spare:8;

} MSG1_STATUS;


typedef struct _MSG1_CMD

{

MSG_HEADER标题;

unsigned int idx:1;

unsigned int jdx:3;

} MSG1_CMD;


类CMDBase

{

public:

virtual~CMDBase(){}

/ *你对这些命令执行了哪些操作?

virtual void operation1()= 0;

virtual void operation2()= 0; * /

};

模板< class CMD>

class CMDHolder:public CMDBase

{

public:

CMDHolder(unsigned char const * buffer)

{

memcpy(& m_CMDStruct,buffer,sizeof) m_CMDStruct);

}


/ *虚拟空操作1()

{

//使用重载的全局函数?

structOperation1(m_CMDStruct);

}


虚拟void operation2()

{

structOperation2(m_CMDStruct);

} * /

私人:

CMD m_CMDStruct;

};


类CMDFactory

{

public:

static CMDFactory&安培;实例()

{

CMDFactory fact;

返回事实;

}

//注册创建者

模板< class T> void Register(int Id)

{

m_creators [Id] = CMDCreator< T> ;;

}

//取消注册创建者

bool取消注册(const int& Id)

{

返回m_creators.erase(Id)== 1;

}


CMDBase *创建(unsigned char const * buffer)

{

// MSG_HEADER * msg_id = reinterpret_cast< MSG_HEADER *>(缓冲区);

MSG_HEADER * msg_id; //只有在这里因为reinterpret_cast错误

投诉


//插入错误检查!

return(m_creators [msg_id->来源])(缓冲区);

}

reinterpret_cast针对常量

缓冲区和非常量MSG_HEADER *生成错误。 ??


return(m_creators [msg_id-> source])(缓冲区); //返回这里可能是

a有点混乱


私有:

typedef CMDBase *(* CMDCreator_t)(unsigned char const * );


模板< class T>

静态CMDBase * CMDCreator(unsigned char const * buffer)

{

返回新的T(缓冲区);

}


std :: map< int,CMDCreator_t> m_creators;

};


int main(无效)

{

//调用一次,在初始化函数中:

CMDFactory :: instance()。寄存器< MSG2_STATUS> (1);

CMDFactory :: instance()。注册< MSG1_STATUS> (2);

//在你的命令处理循环中:

unsigned char buffer [512];

// Read_1553_Data(CHANNEL_FIVE,& ;缓冲区);

CMDBase * newCommand = CMDFactory :: instance()。创建(缓冲区);


// newCommand-> operation1(); //你想用它做什么

//可能把它添加到一个队列< CMDBase *>?

//myqueue.push(newCommand);


返回EXIT_SUCCESS;

}

解决方案

2003年10月2日03:57 :29 -0700, mp********@hotmail.com (MPowell)写道:

让我们假设new_command的返回值是MSG2_STATUS

我的意图是通过调用CMDHolder来记忆数据并且
有一个函数''将检索''存储''数据的副本。后者我不确定该怎么办。有任何帮助。


好​​吧,我可以修复代码中的错误,但是你必须解释代码的意图

。你想用你收到的消息

怎么办?您是否需要根据收到的消息类型执行某些操作?

CMDBase *创建(unsigned char const * buffer)
{
// MSG_HEADER * msg_id = reinterpret_cast< MSG_HEADER *>(缓冲区);
MSG_HEADER * msg_id; //只有在这里因为reinterpret_cast错误

//插入错误检查!
return(m_creators [msg_id-> source])(缓冲区);
}


上面的函数应该更像这样:


CMDBase *创建(unsigned char const * buffer)

{

MSG_HEADER const * msg_id = reinterpret_cast< MSG_HEADER

const *>(缓冲区);

map_t :: const_iterator i = m_creators。 find(msg_id-> source);

if(i == m_creators.end())

{

throw runtime_error("无效的来源);

}

其他

{

//通过指针调用创建函数。 />
返回(i->秒)(缓冲区);

}

reinterpret_cast生成关于常量
缓冲区的错误非常数MSG_HEADER *。 ??


使标题const修复你的问题。

return(m_creators [msg_id-> source])(buffer); //返回这里可能会有点混乱




以上是通过函数指针实现的函数调用。

m_creators将源id映射到创建函数指针而不是

为该类型的消息创建Holder对象。上面访问

函数指针并调用函数,传递缓冲区。作为

的第一个参数。 tern中的该函数返回一个新的Holder对象,

用缓冲区初始化。


Tom


MPowell写道:


< snip>


MSG2_STATUS _msg2_stat [2]; //用于双缓冲
MSG1_STATUS _msg1_stat [2]; //用于双缓冲
MSG1_CMD _msg1_cmd [2]; //用于双缓冲

typedef enum
{
_ msg1_cmd = 0,
_ msg1_status,
_ msg2_status
} MSG_ID;



这些变量和枚举器中的每一个都是非法的。标识符

以下划线后跟小写字母开头保留

在全局命名空间中。


只是不要使用以下划线开头的标识符。这是避免这个问题最简单的方法。


-Kevin

-

我的电子邮件地址有效,但会定期更改。

要联系我,请使用最近发布的地址。


>好吧,我可以修复代码中的错误,但你必须解释

代码的意图。你想用你收到的消息怎么办?您是否需要根据收到的消息类型执行某些操作?


考虑


#define ID_ERROR_MASK 0x08 // #defined在翻译单元顶部

#define ID_MASK 0x07 // #defined在翻译单元顶部

int _msg2_header_error_count = 0;

int _msg1_header_error_count = 0;


int _msg2_message_index = 0;

int _msg1_message_index = 0;

//更多


struct _MSG2_STATUS //这里是演示和批次更多这些

{

//为了简单而剥离''东西''。

unsigned int idx:1;

unsigned int ldx:32;

} MSG2_STATUS;


MSG2_STATUS _msg2_message [2]; //用于双缓冲

//更多


创建函数将查看msg_id(它确实如此)然后检查
$ b错误$ b。


if(msg_id& ID_ERROR_MASK)== 0)

{

//如果没有错误看看msg_type

MSG_HEADER msg_type =

((((msg_id>> 4)& ID_MASK)<< 3))| (msg_id&

ID_MASK);


让我们假设现在msg_type映射到上面定义的MSG2_STATUS


开关(msg_type)

{

case _msg2_status://得到状态2消息


//双缓冲它

i = _msg2_message_index ^ 1;

memcpy(& _msg2_message [i],buffer,sizeof(MSG2_STATUS));

_msg2_message_index ^ = 1;

_msg2_message_ready = TRUE;

休息;


case _msg1_status://获得状态1消息


//双缓冲它

i = _msg1_message_index ^ 1;

memcpy(& _msg1_message [i],buffer,sizeof(MSG1_STATUS));

_msg1_message_index ^ = 1;

_msg1_message_ready = TRUE;

休息;

//等等

默认:

休息;

}

其他

{

switch(msg_id)

{

case _msg2_header_error://收到状态2消息

_msg2 _header_error_count ++;

printf(" msg2_header_error =& d",msg2_header_error);

break;

case _msg1_header_error://收到状态2消息

_msg1_header_error_count ++;


//我怀疑通过计数器会是谨慎的。

通过++ ostream方法有值回收

printf(" msg1_header_error =& d",msg1_header_error);

break;

//等等

默认值:

休息;

}

}


现在,双重缓冲数据,增加一个计数器,然后设置一个标志 -

没有错误。对于错误,请增加错误计数器。当前

模板样式的方法肯定更优雅


类中的单独函数应检索最新的

双缓冲区数据。我怀疑(假设我理解模板)每个

缓冲数据将被推到一个容器/持有人/ ??当需要

(120hz处理rountine检索最新的)时,通过调用某个函数来检索

,模板参数为

结构。


最后,各个结构构成了整个结构的一部分。即

struct OVERALL

{

MSG1_TYPE msg1;

MSG2_TYPE msg2;

还有更多。

}


一个单独的函数将检索''整体''。


本质上,一个获取数据并保存

请求者数据的模板

CMDBase * Create(unsigned char const * buffer)
{
// MSG_HEADER * msg_id = reinterpret_cast< MSG_HEADER *>(缓冲区);
MSG_HEADER * msg_id; //只有在这里因为reinterpret_cast错误

//插入错误检查!
return(m_creators [msg_id-> source])(缓冲区);
}
上面的函数应该更像这样:

CMDBase * Create(unsigned char const * buffer)
{
MSG_HEADER const * msg_id = reinterpret_cast< MSG_HEADER
const *>(缓冲区);
map_t :: const_iterator i = m_creators.find(msg_id-> source);




map_t错误? ?

if(i == m_creators.end())
{
抛出runtime_error(无效的来源);
}
else
{
//通过指针调用create函数。
return(i-> second)(缓冲区);
}

reinterpret_cast相对于常量
缓冲区和非常量MSG_HEADER *生成错误。 ??



使标题const修复你的问题。

return(m_creators [msg_id-> source])(buffer); //返回这里可能会有点混乱



以上是通过函数指针实现的函数调用。
m_creators将源id映射到创建函数指针比可以为该类型的消息创建Holder对象。以上访问函数指针并调用函数,传递缓冲区。作为
的第一个参数。这个函数在tern中返回一个新的Holder对象,用缓冲区初始化。

Tom




Tom,真正适用于援助。如有必要,请随时使用我的电子邮件

地址。


Lets suppose the return value on new_command is MSG2_STATUS

My intent then is to memcpy the data via the call to CMDHolder and
have a function that''ll retrieve a copy of the ''stored'' data. The
latter I''m unsure how to do. Any help appreaciated.
#include <iostream>
#include <map>
using namespace std;

int msg2_status_index = 0;
int msg1_status_index = 0;
int msg1_cmd_index = 0;

MSG2_STATUS _msg2_stat[ 2 ]; // used for double buffering
MSG1_STATUS _msg1_stat[ 2 ]; // used for double buffering
MSG1_CMD _msg1_cmd[ 2 ]; // used for double buffering

typedef enum
{
_msg1_cmd = 0,
_msg1_status,
_msg2_status
} MSG_ID;

typedef struct // this is ++. Why use typedef. ''details'' I suppose
{
MSG_ID source;
unsigned int msg_length : 12;
unsigned int count : 4;
} MSG_HEADER;

typedef struct _MSG2_STATUS
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
unsigned int kdx : 4;
unsigned int spare : 24;
unsigned int ldx : 32;
} MSG2_STATUS;

typedef struct _MSG1_STATUS
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
unsigned int kdx : 4;
unsigned int spare : 8;
} MSG1_STATUS;

typedef struct _MSG1_CMD
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
} MSG1_CMD;

class CMDBase
{
public:
virtual ~CMDBase(){}
/* what operations do you perform on these commands?
virtual void operation1() = 0;
virtual void operation2() = 0; */
};
template <class CMD>
class CMDHolder: public CMDBase
{
public:
CMDHolder(unsigned char const* buffer)
{
memcpy(&m_CMDStruct, buffer, sizeof m_CMDStruct);
}

/* virtual void operation1()
{
//use overloaded global functions?
structOperation1(m_CMDStruct);
}

virtual void operation2()
{
structOperation2(m_CMDStruct);
} */
private:
CMD m_CMDStruct;
};

class CMDFactory
{
public:
static CMDFactory& instance()
{
CMDFactory fact;
return fact;
}

// Register the creator
template <class T> void Register(int Id)
{
m_creators[Id] = CMDCreator<T>;
}
// unregister creator
bool Unregister( const int& Id )
{
return m_creators.erase( Id ) == 1;
}

CMDBase* Create(unsigned char const* buffer)
{
//MSG_HEADER* msg_id = reinterpret_cast<MSG_HEADER*>(buffer);
MSG_HEADER* msg_id; // only here because reinterpret_cast error
complaint

//insert error checking!
return (m_creators[msg_id->source])(buffer);
}
reinterpret_cast generates an error with respect to the constant
buffer and the non constant MSG_HEADER*. ??

return (m_creators[msg_id->source])(buffer); // return here might be
a bit confusing

private:
typedef CMDBase* (*CMDCreator_t)(unsigned char const*);

template <class T>
static CMDBase* CMDCreator(unsigned char const* buffer)
{
return new T(buffer);
}

std::map<int, CMDCreator_t> m_creators;
};

int main ( void )
{
//called once, in initialization function:
CMDFactory::instance().Register<MSG2_STATUS> (1);
CMDFactory::instance().Register<MSG1_STATUS> (2);
// inside your command processing loop:
unsigned char buffer[512];
// Read_1553_Data(CHANNEL_FIVE, &buffer);
CMDBase* newCommand = CMDFactory::instance().Create(buffer);

// newCommand->operation1(); //whatever you want to do with it
//maybe add it to a queue<CMDBase*>?
//myqueue.push(newCommand);

return EXIT_SUCCESS;
}

解决方案

On 2 Oct 2003 03:57:29 -0700, mp********@hotmail.com (MPowell) wrote:

Lets suppose the return value on new_command is MSG2_STATUS

My intent then is to memcpy the data via the call to CMDHolder and
have a function that''ll retrieve a copy of the ''stored'' data. The
latter I''m unsure how to do. Any help appreaciated.
Well, I can fix the errors in the code, but you''ll have to explain
what the code is meant to do. What do you want to do with the messages
that you receive? Do you need to perform some action depending on the
type of message you receive?
CMDBase* Create(unsigned char const* buffer)
{
//MSG_HEADER* msg_id = reinterpret_cast<MSG_HEADER*>(buffer);
MSG_HEADER* msg_id; // only here because reinterpret_cast error
complaint

//insert error checking!
return (m_creators[msg_id->source])(buffer);
}
The above function should go more like this:

CMDBase* Create(unsigned char const* buffer)
{
MSG_HEADER const* msg_id = reinterpret_cast<MSG_HEADER
const*>(buffer);
map_t::const_iterator i = m_creators.find(msg_id->source);
if (i == m_creators.end())
{
throw runtime_error("Invalid source");
}
else
{
//call create function through pointer.
return (i->second)(buffer);
}
reinterpret_cast generates an error with respect to the constant
buffer and the non constant MSG_HEADER*. ??
Making the header const fixes your problem.
return (m_creators[msg_id->source])(buffer); // return here might be
a bit confusing



The above is actuall a function call made through a function pointer.
m_creators maps source id onto a creation function pointer than can
create the Holder object for messages of that type. The above accesses
that function pointer and calls the function, passing "buffer" as the
first parameter. That function in tern returns a new Holder object,
initialized with the buffer.

Tom


MPowell wrote:

<snip>


MSG2_STATUS _msg2_stat[ 2 ]; // used for double buffering
MSG1_STATUS _msg1_stat[ 2 ]; // used for double buffering
MSG1_CMD _msg1_cmd[ 2 ]; // used for double buffering

typedef enum
{
_msg1_cmd = 0,
_msg1_status,
_msg2_status
} MSG_ID;



Every one of these variables and enumerators is illegal. Identifiers
beginning with an underscore followed by a lowercase letter are reserved
in the global namespace.

Just don''t use identifiers beginning with an underscore. It''s the
easiest way to avoid this problem.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.


> Well, I can fix the errors in the code, but you''ll have to explain

what the code is meant to do. What do you want to do with the messages
that you receive? Do you need to perform some action depending on the
type of message you receive?
Consider

#define ID_ERROR_MASK 0x08 // #defined at top of the translation unit
#define ID_MASK 0x07 // #defined at top of the translation unit
int _msg2_header_error_count = 0;
int _msg1_header_error_count = 0;

int _msg2_message_index = 0;
int _msg1_message_index = 0;
// lots more

struct _MSG2_STATUS // here for demo and lots more of these
{
// for simplicity strip out ''stuff''.
unsigned int idx : 1;
unsigned int ldx : 32;
} MSG2_STATUS;

MSG2_STATUS _msg2_message[ 2 ]; // for double buffering
// lots more

The Create function will look at the msg_id (which it does) then check
for error.

if (msg_id & ID_ERROR_MASK) == 0 )
{
// if no error look at msg_type
MSG_HEADER msg_type =
(((( msg_id >> 4 ) & ID_MASK ) <<3 )) | ( msg_id &
ID_MASK );

Lets suppose now the msg_type maps to MSG2_STATUS defined above

switch (msg_type)
{
case _msg2_status: //got a status 2 message

// double buffer it
i = _msg2_message_index ^ 1;
memcpy( &_msg2_message[i], buffer, sizeof(MSG2_STATUS) );
_msg2_message_index ^= 1;
_msg2_message_ready = TRUE;
break;

case _msg1_status: //got a status 1 message

// double buffer it
i = _msg1_message_index ^ 1;
memcpy( &_msg1_message[i], buffer, sizeof(MSG1_STATUS) );
_msg1_message_index ^= 1;
_msg1_message_ready = TRUE;
break;
// and so on
default:
break;
}
else
{
switch( msg_id )
{
case _msg2_header_error: //got a status 2 message
_msg2_header_error_count++;
printf (" msg2_header_error = &d ", msg2_header_error);
break;
case _msg1_header_error: //got a status 2 message
_msg1_header_error_count++;

// I suspect it''d be prudent to pass in the counters and
have values returend by the ++ ostream approach
printf (" msg1_header_error = &d ", msg1_header_error);
break;
// and so on
default:
break;
}
}

So now, double buffer the data,increment a counter, then set a flag -
for no errors. For errors, increment an error counter. The current
template style approach is certainly more elegant

A separate function within the class should retrieve the most current
double buffer data. I suspect (assuming i understand templates) each
buffered data will be ''pushed'' into a container/holder/?? and when
necessary (a 120hz processing rountine retrieves the latest) retrieved
via a call to some function with the template parameter being the
appropriate struct.

Lastly, the individual structs form a part of an overall struct. ie
struct OVERALL
{
MSG1_TYPE msg1;
MSG2_TYPE msg2;
lots more.
}

A separate function will retrieve the ''overall''.

In essence, a template to ''get'' the data and hold data for the
requestor

CMDBase* Create(unsigned char const* buffer)
{
//MSG_HEADER* msg_id = reinterpret_cast<MSG_HEADER*>(buffer);
MSG_HEADER* msg_id; // only here because reinterpret_cast error
complaint

//insert error checking!
return (m_creators[msg_id->source])(buffer);
}
The above function should go more like this:

CMDBase* Create(unsigned char const* buffer)
{
MSG_HEADER const* msg_id = reinterpret_cast<MSG_HEADER
const*>(buffer);
map_t::const_iterator i = m_creators.find(msg_id->source);



map_t error ??
if (i == m_creators.end())
{
throw runtime_error("Invalid source");
}
else
{
//call create function through pointer.
return (i->second)(buffer);
}

reinterpret_cast generates an error with respect to the constant
buffer and the non constant MSG_HEADER*. ??



Making the header const fixes your problem.

return (m_creators[msg_id->source])(buffer); // return here might be
a bit confusing



The above is actuall a function call made through a function pointer.
m_creators maps source id onto a creation function pointer than can
create the Holder object for messages of that type. The above accesses
that function pointer and calls the function, passing "buffer" as the
first parameter. That function in tern returns a new Holder object,
initialized with the buffer.

Tom



Tom, truly appreaciate the assistance. Feel free to use my email
address if necessary.


这篇关于实施细节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆