C++ 如何在另一个类中正确使用类成员?

C++ 如何在另一个类中正确使用类成员?,c++,class,public,C++,Class,Public,我试图使用另一个类的类成员,将类uart添加到类解析器:public uart 但是我不能在解析器类中使用members变量,例如bufer_size、buffer或state Enum。值没有改变或更新。我可以使用这些变量的唯一方法是将它们用作外部变量,但我希望以类成员的方式来做 请在下面找到我的代码: 主要内容: 解析器.h 我应该将上述内容用作公共类还是将其添加为好友类,还是仅用作外部变量?最初的问题显然是使用了错误的格式说明符: void parser::test() {

我试图使用另一个类的类成员,将类uart添加到类解析器:public uart

但是我不能在解析器类中使用members变量,例如bufer_size、buffer或state Enum。值没有改变或更新。我可以使用这些变量的唯一方法是将它们用作外部变量,但我希望以类成员的方式来做

请在下面找到我的代码:

主要内容:

解析器.h


我应该将上述内容用作公共类还是将其添加为好友类,还是仅用作外部变量?

最初的问题显然是使用了错误的格式说明符:

void parser::test()
{       
    printf("state %s", state);
    //            ^^
}
%s仅代表C字符串i。E以null结尾的字符数组。在这里,状态被解释为一个指针,但它指向无效地址未定义的行为,所以您知道应用程序可能在能够产生任何输出之前就崩溃了

即使状态确实包含有效地址,您仍然会遇到未定义的行为,因为%s需要char*类型的参数以避免UB,您需要强制转换

使用正确的格式说明符解决此问题:

printf("state %u", static_cast<unsigned int>(state));
})

或者,您可以通过指向构造函数的指针或引用在外部提供它,并将其存储为构造函数,但随后您也将很快进入终身管理,我建议您带着更多的经验返回更高级的概念

不过,您应该习惯的是:封装。不要公开成员变量,除非您真的希望从任何地方更改它们。例如,缓冲区是私有的,甚至不受保护的热门候选

最后,buffer_size:如果您打算用它来计算当前缓冲区中的值的数量,那么它就可以了。如果它代表可以存储的最大数据数量,则它是冗余的。只要需要,就可以通过sizeofbuffer/sizeof*buffer获取大小,除非数组已衰减为指针!。按第一个元素的大小划分是必要的,因为sizeof总是以字节而不是以元素的数量来传递大小


元素数量中的大小是通过std::array::Size得到的;由于其优越的接口,您应该更喜欢原始阵列!甚至可能是一个更好的选择?

离题:不要实现单例模式并提供公共构造函数!标准甚至保证了更好的变体是线程安全的:SC&instance{static SC;return SC;}您在哪里尝试使用这些成员的?我在解析器中看不到任何这样做的代码。你们得到了什么错误消息?当你们说,我不能在解析器类中使用members变量时,这到底意味着什么?编译器是否无法接收您的代码?成功编译后运行代码时是否有错误?Fwiw,这不是一个合适的单例模式,即使有这样的事情,但不知何故,我不认为这与你真正遇到的任何问题有关。即使编译缓冲区大小不确定,memset调用也会导致运行时错误。由于解析器继承自uart,创建一个解析器对象将在指向同一实例的两个单例中结束,可能会丢失以前创建的单独uart单例对象!这是您想要的吗?忽略%s问题太容易了,因为您的示例不是最简单的。看一看。您应该删除与错误无关的所有部分。迭代步骤:删除部分代码,测试问题是否仍然存在,如果是,继续,否则保留刚刚删除的代码部分。您可以从整个类开始,完成后,剩下的类的函数,最后是函数块。。。在这个过程中,很可能你自己已经发现了问题,但不是在给定的情况下……哥们,谢谢你的帮助,我绝对应该学习更多关于编程模式的知识,我只是在使用singleton,因为我正在编写的一些代码使用它。我在C++世界是新的,所以我还没有足够的经验
#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;      
    }       
}
#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;
    }       
};
#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;    
}
void parser::test()
{       
    printf("state %s", state);
    //            ^^
}
printf("state %u", static_cast<unsigned int>(state));
class parser // : public uart
{
    uart m_uart;
public:
    // ...
    void test()
    {
        printf("%u", static_cast<unsigned int>(m_uart.state);
    }