在另一个 class 中使用 class 成员的正确方法是什么?
How is the proper way to use class members in another class?
我正在尝试使用来自不同 class 的 class 成员,将“class uart”添加到“class 解析器:public uart"
但我不能在解析器 class 中使用成员变量,例如(bufer_size、缓冲区或状态枚举,值不会更改或更新)这是我使用这些变量的唯一方法将它们用作外部变量,但我想以 class 成员方式进行。
下面请找到我的代码:
主要内容:
#include <stdio.h>
#include "parser.h"
int main()
{
parser m_parser;
m_parser.test();
return 0;
}
uart.h
#include <stdint.h>
#include <stdio.h>
//extern uint16_t buffer_size;
//extern char buffer[1024];
class uart
{
public:
// Construction
uart();
//..... some functions
void Initialize();
//members
enum STATE_enum
{
Buffering_message=0,
Message_received,
Buffering_empty
};
STATE_enum state;
uint16_t buffer_size;
char buffer[1024];
protected:
// static void UARTHandler(app_uart_evt_t * p_event);
void Message();
// Singleton instance
static uart * m_instance;
};
uart.cpp
#include "uart.h"
//uint16_t buffer_size=0;
//char buffer[1024];
uart * uart::m_instance = 0; // Singleton instance
uart::uart()// Construction
{
state = Buffering_empty;
m_instance = this;
}
void uart::Initialize()
{
}
/*void UART::UARTHandler(app_uart_evt_t * p_event)
{
Message();
}*/
void uart::Message()
{
uint8_t value;
// while ((app_uart_get(&value)) == NRF_SUCCESS) //specific function from my microcontroller stack for reading RX bytes
{
if(value == 0x0A ) // message end /r
state = Message_received;
}
switch (state)
{
case Message_received:
printf("message:[%s] buffer_size:[%d]", buffer,buffer_size); //printf fine from there
break;
case Buffering_message:
buffer[buffer_size++] = value;
break;
default:
break;
}
}
parser.h
#include <stdio.h>
#include <stdint.h>
#include "uart.h"
class parser : public uart
{
public:
parser();
void test();
static parser * m_instance;
static inline parser & Instance()// Singleton access
{
return *m_instance;
}
};
parser.cpp
#include "parser.h"
class parser * parser::m_instance = 0;
// Constructor
parser::parser()
{
m_instance = this;
}
void parser::test()
{
printf("state %s", state); // sending AT command
// memset(buffer, 0, buffer_size);
// buffer_size = 0;
}
我应该将上面的作为 Public class 或将其添加为朋友 class,还是仅用作外部变量?
最初的问题显然是使用了错误的格式说明符:
void parser::test()
{
printf("state %s", state);
// ^^
}
%s
仅适用于 C 字符串(即空终止 char
数组)。在这里,state
被解释为一个指针,但它指向无效地址(未定义的行为),因此您的应用程序可能在它能够产生任何输出之前就崩溃了。
即使 state
did 包含有效地址,您仍然会遇到未定义的行为,因为 %s
需要类型为 [=18= 的参数](为了避免UB,你需要施法)。
使用正确的格式说明符解决问题:
printf("state %u", static_cast<unsigned int>(state));
您仍然需要转换以避免 UB,因为 %u
需要 unsigned int
,但您的枚举不需要(或者您可以使用 %d
并转换为 int
) .
显然,您现在也尝试(因为没有发现真正的错误)通过使用单例来绕过您假设的事情——不幸的是,很糟糕实施该模式,您的设计存在缺陷。
如何修复?首先,放弃单身人士。在给定的情况下绝对没有必要。然后三思而后行(以下已经是一个问题before):解析器真的是UART吗?不考虑代码,只考虑概念,我明明说"no"。所以你也不应该让从uart
继承parser
。而是让它聚合一个:
class parser // : public uart
{
uart m_uart;
public:
// ...
void test()
{
printf("%u", static_cast<unsigned int>(m_uart.state);
}
};
或者,您可以通过指针或引用(对构造函数)在外部提供它并按原样存储它,但是您很快就会 运行 进入生命周期管理,我会使用更高级的概念建议你回来多一点经验...
不过,您应该 习惯的是:封装。不要创建成员变量 public 除非你 真的 希望它们从 任何地方 改变。例如,buffer
是私有(甚至未受保护)的热门候选对象。
最后buffer_size
:如果你打算用它来计算缓冲区中当前值的数量,那么它很好。如果它代表可以存储的最大数据数,那么它就是冗余的。在任何需要的地方,你可以通过 sizeof(buffer)/sizeof(*buffer)
获得大小(除非数组已经衰减为指针!)。按第一个元素的大小划分是必要的,因为 sizeof
始终以字节为单位提供大小, 而不是 的元素数量。
元素数量的大小是你得到的std::array::size
;你应该更喜欢 std::array over raw arrays due to the superior interface! Maybe std::vector even 是更好的选择吗?
我正在尝试使用来自不同 class 的 class 成员,将“class uart”添加到“class 解析器:public uart"
但我不能在解析器 class 中使用成员变量,例如(bufer_size、缓冲区或状态枚举,值不会更改或更新)这是我使用这些变量的唯一方法将它们用作外部变量,但我想以 class 成员方式进行。
下面请找到我的代码:
主要内容:
#include <stdio.h>
#include "parser.h"
int main()
{
parser m_parser;
m_parser.test();
return 0;
}
uart.h
#include <stdint.h>
#include <stdio.h>
//extern uint16_t buffer_size;
//extern char buffer[1024];
class uart
{
public:
// Construction
uart();
//..... some functions
void Initialize();
//members
enum STATE_enum
{
Buffering_message=0,
Message_received,
Buffering_empty
};
STATE_enum state;
uint16_t buffer_size;
char buffer[1024];
protected:
// static void UARTHandler(app_uart_evt_t * p_event);
void Message();
// Singleton instance
static uart * m_instance;
};
uart.cpp
#include "uart.h"
//uint16_t buffer_size=0;
//char buffer[1024];
uart * uart::m_instance = 0; // Singleton instance
uart::uart()// Construction
{
state = Buffering_empty;
m_instance = this;
}
void uart::Initialize()
{
}
/*void UART::UARTHandler(app_uart_evt_t * p_event)
{
Message();
}*/
void uart::Message()
{
uint8_t value;
// while ((app_uart_get(&value)) == NRF_SUCCESS) //specific function from my microcontroller stack for reading RX bytes
{
if(value == 0x0A ) // message end /r
state = Message_received;
}
switch (state)
{
case Message_received:
printf("message:[%s] buffer_size:[%d]", buffer,buffer_size); //printf fine from there
break;
case Buffering_message:
buffer[buffer_size++] = value;
break;
default:
break;
}
}
parser.h
#include <stdio.h>
#include <stdint.h>
#include "uart.h"
class parser : public uart
{
public:
parser();
void test();
static parser * m_instance;
static inline parser & Instance()// Singleton access
{
return *m_instance;
}
};
parser.cpp
#include "parser.h"
class parser * parser::m_instance = 0;
// Constructor
parser::parser()
{
m_instance = this;
}
void parser::test()
{
printf("state %s", state); // sending AT command
// memset(buffer, 0, buffer_size);
// buffer_size = 0;
}
我应该将上面的作为 Public class 或将其添加为朋友 class,还是仅用作外部变量?
最初的问题显然是使用了错误的格式说明符:
void parser::test()
{
printf("state %s", state);
// ^^
}
%s
仅适用于 C 字符串(即空终止 char
数组)。在这里,state
被解释为一个指针,但它指向无效地址(未定义的行为),因此您的应用程序可能在它能够产生任何输出之前就崩溃了。
即使 state
did 包含有效地址,您仍然会遇到未定义的行为,因为 %s
需要类型为 [=18= 的参数](为了避免UB,你需要施法)。
使用正确的格式说明符解决问题:
printf("state %u", static_cast<unsigned int>(state));
您仍然需要转换以避免 UB,因为 %u
需要 unsigned int
,但您的枚举不需要(或者您可以使用 %d
并转换为 int
) .
显然,您现在也尝试(因为没有发现真正的错误)通过使用单例来绕过您假设的事情——不幸的是,很糟糕实施该模式,您的设计存在缺陷。
如何修复?首先,放弃单身人士。在给定的情况下绝对没有必要。然后三思而后行(以下已经是一个问题before):解析器真的是UART吗?不考虑代码,只考虑概念,我明明说"no"。所以你也不应该让从uart
继承parser
。而是让它聚合一个:
class parser // : public uart
{
uart m_uart;
public:
// ...
void test()
{
printf("%u", static_cast<unsigned int>(m_uart.state);
}
};
或者,您可以通过指针或引用(对构造函数)在外部提供它并按原样存储它,但是您很快就会 运行 进入生命周期管理,我会使用更高级的概念建议你回来多一点经验...
不过,您应该 习惯的是:封装。不要创建成员变量 public 除非你 真的 希望它们从 任何地方 改变。例如,buffer
是私有(甚至未受保护)的热门候选对象。
最后buffer_size
:如果你打算用它来计算缓冲区中当前值的数量,那么它很好。如果它代表可以存储的最大数据数,那么它就是冗余的。在任何需要的地方,你可以通过 sizeof(buffer)/sizeof(*buffer)
获得大小(除非数组已经衰减为指针!)。按第一个元素的大小划分是必要的,因为 sizeof
始终以字节为单位提供大小, 而不是 的元素数量。
元素数量的大小是你得到的std::array::size
;你应该更喜欢 std::array over raw arrays due to the superior interface! Maybe std::vector even 是更好的选择吗?