(此文章仅作为单片机c程序员使用class的入门,不涉及c++其他特性)

class 与 struct的简单对比

c++的类class在不使用其他特性的情况下就是大号的结构体,下面从多个方面对比class与struct

这是一个简单的结构体,成员name,age。输出结果:姓名:张三 ,年龄:18,我们再看看class

struct student{
    char name[20];
    int age;
};

int main()
{
    struct student zhangsan;
    strcpy(zhangsan.name, "张三");
    zhangsan.age = 18;
    printf("姓名:%s ,年龄:%d",zhangsan.name,zhangsan.age);
    return 0;
}

class对比:输出结果:姓名:张三 ,年龄:18

class student{
public:
    char name[20];
    int age;
};

int main()
{
    student zhangsan;
    strcpy(zhangsan.name, "张三");
    zhangsan.age = 18;
    printf("姓名:%s ,年龄:%d",zhangsan.name,zhangsan.age);
    return 0;
}

可以看到,在class 与 struct在使用上几乎没有区别。但是在类中,有“pubilic:”这是权限的意思,意思为公共权限,你可以任意的修改它的成员age,name(c++编程一般属性作为私有权限)。

class 的指针使用

同样的,作为大号的struct,它们在指针的使用上也是一模一样的。此时输出:姓名:张三 ,年龄:88 

class student{
public:
    char name[20];
    int age;
};

int main()
{
    student zhangsan;
    strcpy(zhangsan.name, "张三");
    zhangsan.age = 18;
    student *p = &zhangsan;
    p->age = 88;
    printf("姓名:%s ,年龄:%d",zhangsan.name,zhangsan.age);
    return 0;
}

但是,我们使用c++的class开发可以使用面向对象的方式管理函数,集成功能,可以非常好的提高代码的可读性与可维护信性且不会有其他的额外性能开销。

class 的构造函数

使用类,我们需要知道构造函数,它与类的名称一致,其主要作用是初始化成员,同样以张三为例子。

class student{
public:
    char name[20];
    int age;

    student(const char *Name,int age);
};

student::student(const char *Name,int Age)
{
    strcpy(name, Name);
    age = Age;
}

int main()
{
    student zhangsan("张三",18);
    student *p = &zhangsan;
    printf("姓名:%s ,年龄:%d",zhangsan.name,zhangsan.age);
    return 0;
}

class的成员除了基础数据类型,还可以是函数,函数中又有许多特殊函数,这里仅介绍构造函数:它与类的名称一致,都是student,在class中声明(也可以在class中定义)。我们来看看这个结构。我们定义class也可以没有构造函数。不过权限至少要一个哦,这里我们使用public。

student::student(const char *Name,int Age)

【student::】表明是属于student的函数,xxx::就是属于class xxx的函数,之后的函数定义也是这个意思。

【student(const char *Name,int Age)】这就是构造函数的函数名了,不过构造函数是没有返回值的。

class的函数定义

class student{
public:
    char name[20];
    int age;
    //构造函数
    student(const char *Name,int age);
    //设置年龄
    void set_age(int x){
        age = x;
    }
};

student::student(const char *Name,int Age)
{
    strcpy(name, Name);
    age = Age;
}

int main()
{
    student zhangsan("张三",18);
    zhangsan.set_age(20);
    printf("姓名:%s ,年龄:%d",zhangsan.name,zhangsan.age);
    return 0;
}

这就是在class内部定义一个设置年龄的函数拉,输出结果为姓名:张三 ,年龄:20 

同样的,也能通过指针操作

    student *p = &zhangsan;
    p->set_age(20);

前面我们说了,除了class内定义,还可以class内声明,在外部定义

返回类型void  所属类student::   参数类型int

输出结果:姓名:张三 ,年龄:20 

class student{
public:
    char name[20];
    int age;
    //构造函数
    student(const char *Name,int age);
    //设置年龄
    void set_age(int x);
};

student::student(const char *Name,int Age)
{
    strcpy(name, Name);
    age = Age;
}

void student::set_age(int x){
    age = x;
}
int main()
{
    student zhangsan("张三",18);
    student *p = &zhangsan;
    p->set_age(20);
    printf("姓名:%s ,年龄:%d",zhangsan.name,zhangsan.age);
    return 0;
}

好了,你已经完全学会class with c了,实战一下

GPIO口操作

以stm32f1系类为例子,将GPIO口封装为一个类,构造函数初始化GPIO口模式,设置高低电平

.h文件:

.h文件
class GPIO_t{
	private://私有属性
		GPIO_TypeDef* GPIOx;
		uint32_t GPIO_Pin;
	public:
		GPIO_t(GPIO_TypeDef* gpio_port, uint32_t pin,FlagStatus Pin_State);
		void Hight();
		void Low();
		void Toggle();
		inline uint8_t Read_Pin(uint16_t pin){return LL_GPIO_IsInputPinSet(GPIOx,GPIO_Pin);}
};

.cpp文件

.cpp文件
//构造函数,初始化GPIO口
GPIO_t::GPIO_t(GPIO_TypeDef* gpio_port, uint32_t pin,FlagStatus Pin_State)
{
	LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIOx = gpio_port;
	GPIO_Pin = pin;
//根据不同的GPIO口使能不同的时钟
	if (GPIOx == GPIOA)
		LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
	else if (GPIOx == GPIOB)
		LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
	else if (GPIOx == GPIOC)
		LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
	else if (GPIOx == GPIOD)
		LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOD);
	
//设置模式
	GPIO_InitStruct.Pin = GPIO_Pin;
	GPIO_InitStruct.Speed = LL_GPIO_MODE_OUTPUT_50MHz;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
	LL_GPIO_Init(GPIOx, &GPIO_InitStruct);
//初始化高低电平
	if (Pin_State == SET) 
    	LL_GPIO_SetOutputPin(GPIOx, GPIO_Pin);
	else 
    	LL_GPIO_ResetOutputPin(GPIOx, GPIO_Pin);
}

/*
* 设置为高电平
*/
void GPIO_t::Hight()
{
	LL_GPIO_SetOutputPin(GPIOx,GPIO_Pin);
}

/*
* 设置为低电平
*/
void GPIO_t::Low()
{
	LL_GPIO_ResetOutputPin(GPIOx,GPIO_Pin);
}

/*
* 翻转目标GPIO口
*/
void GPIO_t::Toggle()
{
	LL_GPIO_TogglePin(GPIOx,GPIO_Pin);
}

操控GPIO口,以GPIOA0为例子,初始化为推挽输出,高电平。设置它为低电平,再翻转它的电平。

你还可以像定义结构体那样定义GPIO_t GPIO2,GPIO3,GPIO4它们都是独立的对象,可以被独立操控。

int main()
{
	GPIO_t GPIO1(GPIOA,LL_GPIO_PIN_0,SET);//初始化为高电平
	GPIO1.Low();//变成低电平
	GPIO1.Toggle();//翻转电平
	while(1)
	{ 
		Delay_ms(1000);
	}
}

现在,将GPIO口的驱动函数集成在GPIO_t的类class中,就好比对函数进行了分类,找起来和维护起来都会方便很多,使用成员时,只需要向结构体那样  使用“.”引出就好了。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐