如何在另一个班级中使用班级成员的正确方法?

时间:2018-08-29 16:13:51

标签: c++ class public

我正在尝试使用来自其他类的类成员,并将“ 类uart ”添加到“ 类解析器:公共uart

但是我不能在解析器类中使用成员变量(例如,bufer_size,buffer或状态Enum值未更改或更新),我可以使用这些变量的唯一方法是将它们用作外部变量,但是我会喜欢以类成员的方式进行操作。

请在下面找到我的代码:

主要

#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;    
}

我应该将以上内容用作公共类,还是将其添加为朋友类,还是直接用作外部变量?

1 个答案:

答案 0 :(得分:1)

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

void parser::test()
{       
    printf("state %s", state);
    //            ^^
}

%s仅适用于C字符串(即以null结尾的char数组)。这里,state被解释为一个指针,但是它指向无效的地址(未定义的行为),因此您的应用程序可能在完全无法产生任何输出之前崩溃了。

即使state did 包含有效地址,您仍然会遭受不确定的行为,因为%s需要类型为char*的参数(以避免UB ,则需要投射)。

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

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

您仍然需要强制转换以避免UB,因为%u要求unsigned int,但您的枚举不是(或者可以使用%d并强制转换为int)。 / p>

显然,您现在也尝试(由于未发现实际错误)通过使用单例来解决您假定的问题–不幸的是,通过严重实施该模式,您对您的设计有缺陷。

如何维修?首先,放下单例。在给定的情况下绝对没有必要。然后再三想(以下是之前的问题):解析器真的是UART吗?我不考虑代码,而是考虑概念,我明确地说“不”。因此,您也不应该让parser中的继承 uart。而是让它汇总一个:

class parser // : public uart
{
    uart m_uart;
public:
    // ...
    void test()
    {
        printf("%u", static_cast<unsigned int>(m_uart.state);
    }

};

或者,您可以通过指针或引用(提供给构造函数)在外部提供它并进行存储,但是随后您也将很快进入生命周期管理,我建议您回到更高级的概念有了更多的经验...

应该习惯的是:封装。除非您真的希望将它们从任何地方更改,否则不要公开成员变量。例如,buffer是私有(甚至未受保护)的热门候选人。

最后buffer_size:如果您打算将其用于对当前 缓冲区中的值进行计数,那很好。如果它表示 可以存储的最大数据量,则它是多余的。无论您在哪里需要它,都可以通过sizeof(buffer)/sizeof(*buffer)获得大小(除非数组已衰减到指针!)。必须将第一个元素的大小相除,因为sizeof总是以字节为单位传送大小,而不是以元素数表示

元素数量的大小是std::array::size得到的;由于界面优越,您应该更喜欢std::array而不是原始数组!也许std::vector甚至是更好的选择?

相关问题