百度站长app,网站建设布局设计,怎么创建公众号写文章,yes风淘宝网站1. 类 我们之前提及过C语言是面向过程的语言#xff0c;其解决问题的方式是关注问题过程#xff0c;然后逐步解决。而C是面向对象编程#xff0c;聚焦于对象#xff0c;依靠多个对象之间的交互关系解决问题。而类这个概念的引入则是面向对象的最深刻体现。
1.1 C中的结构体…1. 类 我们之前提及过C语言是面向过程的语言其解决问题的方式是关注问题过程然后逐步解决。而C是面向对象编程聚焦于对象依靠多个对象之间的交互关系解决问题。而类这个概念的引入则是面向对象的最深刻体现。
1.1 C中的结构体 C兼容C所以C的结构体完全涵盖了C语言中结构体的语法形式。除此之外C结构体也做出了一些改进如定义结构体变量不再一定需要struct关键字不过最大的变化还是体现在结构体内可以定义函数了。 在结构体内定义的函数可以直接使用结构体中的成员变量在调用成员函数时可以直接使用成员访问的方式就行调用函数中的成员变量则会自动被替换为调用结构体变量对应的结构体变量。
struct Stack {//C的结构体内既可以定义变量也可以定义函数//变量int* _arr;int _capacity;int _top;//函数void Init(int capacity 4){_arr (int*)malloc(sizeof(int) * capacity);if (_arr nullptr){perror(malloc fail);return;}_capacity capacity;_top 0;}
};
int main()
{//定义结构体变量可以不加structstruct Stack st1;Stack st2;//调用成员函数st1.Init();st2.Init(8);
} 需要注意的是成员变量的命名尽量加入一些标识使得可以很容易分辨出是一个成员变量以防在成员函数中调用产生分不清的情况。类的成员变量命名也要注意这一点。
1.2 C的类 但是在C中我们一般使用类来替代结构体类的关键字为class。
1.2.1 类的定义
1.2.1.1 声明和定义全部放在类体中 声明和定义同时放在类体中这种方式比较简便就像C语言阶段的声明定义不分离一样。
class Date
{int _year;int _month;int _day;void Show(){cout _year - _month - _day endl;}
};
1.2.1.2 声明放在类的头文件定义放在类的实现文件 这种方法类似于C语言中的声明和变量分离比较规整并且便于合作开发。 这种方法需要注意类的作用域即需要 类名::成员名 来指明成员所属的类域。 date.h #pragma once
class Date
{int _year;int _month;int _day;void Show();
}; date.cpp #includedate.h
void Date::Show()
{cout _year - _month - _day endl;
} 1.2.2 类的访问限定符
1.2.2.1 封装 面向对象有三大特性封装、继承、多态。 封装指的是将数据和操作数据的方法进行有机结合隐藏对象的属性和实现细节仅对外公开接口来和对象进行交互。在C中可以借助访问限定符来控制哪些成员或方法可以在类外部使用从而实现封装的特性。
1.2.2.2 访问限定符 C的访问限定符有三个public公有protected保护private私有。这三个访问限定符只有public修饰的成员支持在类外被访问而protected和private是不可以的。 访问限定符在C中的形式是访问限定符带一个冒号。其限定范围是自符号起到下一个访问限定符或类结束为止。 class成员的默认访问权限是privatestruct成员的默认访问权限是public。
struct Stack {int* _arr;int _capacity;int _top;void Init(int capacity 4){_arr (int*)malloc(sizeof(int) * capacity);if (_arr nullptr){perror(malloc fail);return;}_capacity capacity;_top 0;}
private:void Show(){}
};
class Date
{int _year;int _month;int _day;public:void Init(int year 2000, int month 1, int day 1){_year year;_month month;_day day;}void Show(){cout _year - _month - _day endl;}
};int main()
{struct Stack st1;//struct默认访问权限是publicst1.Init();int a st1._capacity;//st1.Show();//errorDate d1;//class默认访问权限是private//d1._year 2024; //errord1.Init();d1.Show();
}
1.2.3 类的实例化 类和结构体在一定程度上是相似的。在定义结构体或类的时候只是限定了有哪些成员类似于给出图纸但此时并没有在内存中分配空间。直到我们创建结构体变量或类对象这时候才会在内存中开辟空间我们才能正常访问使用。这一步就叫做类的实例化。
class Date
{int _year;int _month;int _day;public:void Init(int year 2000, int month 1, int day 1){_year year;_month month;_day day;}void Show(){cout _year - _month - _day endl;}
};int main()
{//Date.Init(); //error 没有实例化Date d1;d1.Init();
}
1.2.4 类的大小 类的大小计算方式与结构体相同。类中的成员函数不会存放在对象开辟的空间中而是统一放在代码段中。所以类的大小只与成员变量有关而与成员函数无关。当类中没有成员函数时编译器中会为这个空类对象分配一个字节的空间作为占位。
class C1
{int a;char c;double d;void func(){}
};
class C2
{void func(){}
};
class C3
{};int main()
{cout sizeof(C1) endl; //16cout sizeof(C2) endl; //1cout sizeof(C3) endl; //1
}
1.3 this指针 在了解了这么多后有一个问题在调用成员函数时我们并没有传递对象的相关信息函数凭什么知道我们调用的对象是d1而不是d2呢这是因为this指针发挥了作用。 在C中编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数这也就是我们所要介绍的this指针。函数调用时this指针会指向当前对象(函数运行时调用该函数的对象)在函数体中所有“成员变量” 的操作都是通过this指针去访问的。只不过所有的操作对用户是透明的即用户不需要来传递由编译器自动完成。 我们可以通过观察汇编代码发现这个隐藏的this指针传参。 class Date
{int _year;int _month;int _day;public://void Init(Date* const this, int year 2000, int month 1, int day 1)void Init(int year 2000, int month 1, int day 1) {this-_year year;_month month;_day day;}//void Show(Date* const this)void Show(){cout _year - _month - _day endl;}
};
int main()
{Date d1;d1.Init(2024, 2, 25);d1.Show();
} 我们对this指针进行总结
①this指针的类型是 类类型* const这说明在函数成员内不可以修改this但是修改通过this解引用的值。
②this指针只能在成员函数内使用。
③对象中并不储存this指针在成员函数调用时将对象的地址作为实参传递给成员函数的this形参。
④this指针真实存在但是传参是由编译器自动完成的我们不可以在实参和形参位置显式写出this指针的传递。
⑤我们可以在成员函数内部使用this指针。this作为参数存储在栈中。
class C
{
public:int _a;void func(){cout func() endl; //没有使用this指针所以没有空指针解引用不报错//cout _a endl; //error 实际上是this-_athis是空指针所以报错}
};
int main()
{C c1;C* pc nullptr;pc-func(); //- 不解引用而是将pc作为参数传给thisthis接收参数值为nullptr(*pc).func(); //. 不解引用也是将pc传给this指针this接收参数值为nullptr
} 在成员函数调用时-或.两个操作符并不进行解引用而是表示将传给this指针的对象是谁所以在主函数中并未报错在成员函数中访问成员变量时才会对this解引用。