一、初识
1.1 基本概念
- 类定义:面向对象程序设计核心,封装一类数据和方法的蓝图,以实类来初始化及调用
- 类构成:类变量,类方法,且其作用域及调用受访问修饰符限制
- 类变量:不同对象会开辟不同的存储空间来存放类变量
- 类方法
- 声明及定义:类内声明,可在类内或类外定义
- 写法:常规在类内声明(放在头文件*.h中),在类外定义(实现文件*.cpp中)
- 本质:同一类的所有对象共用同一组类方法,即每种方法只有一个副本
- 访问修饰符
- private:默认,只有定义的类可以访问,派生类和类外都不可直接访问
- public:开放访问,定义类方法位置,即类接口定义位置,外部需要点运算符调用
- protected:定义的类和派生类可以访问,外部不可直接访问
- 重载:类中,方法名相同,参数不同,返回类型无限制。 每个重载方法都必须有唯一的参数类型列表
1.2 类基础写法
-
功能意图:类为长方体,通过类函数设置长方体长宽,进而求长方体底面积
-
基础代码写法1
#include <iostream> using namespace std; class Box { // private私有成员访问修饰符: // 通常是用来封装类的数据,私有函数,只有定义的类可访问 private: double _length; double _width; string _name; // public公有成员访问修饰符: // 通常是用来定义类的函数,进而对外界提供调用类相应功能的接口 public: // 类的构造函数:函数名同类名,通常用于初始化类的数据, // 函数体可为空,不可有return语句 Box() { // 类内调用私有变量,写法如下 _length = 5.0; _width = 10.0; _name = "无名" }; // 析构函数:用来显式释放类的存储空间和资源, // 函数体可为空,栈内存选填,堆内存必须 ~Box() { cout << "这是"<< _name << "的析构函数被调用" << endl; }; // 类函数实现一:类外定义,类内声明 void set(const string &name, double length, double width); // 类函数实现二:类内定义,类内声明 void area(void) { // 类内调用私有变量 cout << _name << "的area函数被调用" << endl; double area = _length * _width; cout << "长:" << _length << ",宽:" << _width << endl; cout << "面积为:" << area << endl; }; }; // 类外定义类的函数,注意返回值void,类前缀Box:: void Box::set(const string &name, double length, double width) { // 类外定义类的函数体调用类的私有变量 _name = name; _length = length; _width = width; cout << _name << "的set函数被调用" << endl; } int main() { // 声明定义类:此处调用类的构造函数 Box box1, box2; // box1调用类的set函数 string name = "box1"; box1.set(name, 20.0, 30.0); box1.area(); // box2使用的是类的构造函数赋的值 box2.area(); // 析构函数:此处调用类的析构函数 }
-
返回值显示
box1的set函数被调用 box1的area函数被调用 长:20,宽:30 面积为:600 无名的area函数被调用 长:5,宽:10 面积为:50 这是无名的析构函数被调用 这是box1的析构函数被调用
-
写法2(仅字符串变量不同,返回值同上)
#include <iostream> // 用C风格字符串变量 #include <cstring> using namespace std; class Box { private: double _length; double _width; char _name[10]; public: Box() { _length = 5.0; _width = 10.0; // 字符串赋值 strcpy(_name, "无名"); }; ~Box() { cout << "这是" << _name << "的析构函数被调用" << endl; }; void set(const char *name, double length, double width); void area(void) { cout << _name << "的area函数被调用" << endl; double area = _length * _width; cout << "长:" << _length << ",宽:" << _width << endl; cout << "面积为:" << area << endl; }; }; void Box::set(const char *name, double length, double width) { // 字符串变量深拷贝 strcpy(_name, name); _length = length; _width = width; cout << _name << "的set函数被调用" << endl; } int main() { Box box1, box2; box1.set("box1", 20.0, 30.0); box1.area(); box2.area(); }
1.3 类的内联函数
- 写法(内联函数、堆内存中创建对象、const修饰this)
class Box { private: ... public: ... // const:此函数不修改调用对象,编译时检测 // 修饰隐含传入的this,见下节 void area() const; }; // 内联函数定义:一般只有一个语句的函数用此方法 inline void Box::area() const { cout << "面积是:"_length * _width << endl; } // 以下了解下即可,进阶详解 int main() { // 这是堆内存中创建类对象,指针box1是在栈内存中 Box *box1 = new Box(1, 1); // 指针调用类方法写法 box1->area(); }
1.4 this指针
- 定义:
- 本质:每一个对象都能通过 this 指针来访问自己的地址
- 特性:this 指针是所有成员函数的隐含参数
- 简记:谁调用函数,this就指向谁
- 代码示例
#include <iostream> using namespace std; class Box { private: double _length; public: Box(double length = 0) { _length = length; }; void print() const { // _length:是this->_length的简写 cout << _length; }; void transprint() const { // a、this可以调用本对象任意函数, // b、针对的是对象自己的数据 // c、this是函数隐式传递的 this->print(); }; }; int main() { Box box1(2.0); box1.transprint(); // 屏幕输出2 }
二、构造函数
2.1 三种构造函数写法
- 代码示例(三种构造函数、C风格字符串深拷贝)
#include <iostream> #include <cstring> using namespace std; //------------------类声明------------------// class Box { private: double _length; char _name[10]; public: // 类构造函数重载:注意无返回值 // a、不传参默认构造函数 Box(); // b、带参数的默认构造函数:有默认值的在类声明里写,类外定义不写 Box(const char *name, double length= 2.1); // c、复制构造函数:函数虚实参传递也会用到这个 Box(const Box &obj); void show(); ~Box(){}; }; //------------------类函数定义------------------// // a、若无构造函数:程序会自动创建一个Box::Box(){} Box::Box(void) { // strcpy函数要求第二个参数类型是const char *__src strcpy(_name, "无名"); _length = 1.0; cout << "调用无参构造函数" << endl; } // b、函数可含默认参数,const char *__src为strcpy函数要求 Box::Box(const char *name, double length) { strcpy(_name, name); _length = length; cout << "调用传参构造函数" << endl; } // c、复制构造函数:用已初始化过的类对象初始化类对象 Box::Box(const Box &obj) { strcpy(_name, obj._name); _length = obj._length; cout << "调用复制构造函数" << endl; } void Box::show() { cout << _name << ":" << _length << endl; } //------------------主函数------------------// int main() { // a、调用不传参默认构造函数,不可用Box box1();调用 Box box1; // b、调用传参默认构造函数 Box box2("box2", 2.0); // b、调用传参默认构造函数,使用函数默认参数 Box box3("box3"); // c、调用复制构造函数 Box box4(box2); box1.show(); box2.show(); box3.show(); box4.show(); }
- 程序显示
调用无参构造函数 调用传参构造函数 调用传参构造函数 调用复制构造函数 无名:1 box2:2 box3:2.1 box2:2
2.2 类对象数组
- 功能:批量初始化类对象
- 代码示例
// 类相关见2.1 //------------------主函数------------------// int main() { Box box[3] = {Box("box0", 0), Box(box[0])}; box[0].show(); box[1].show(); box[2].show(); }
Box box[3];
:会三次调用无参构造函数 - 显示
调用传参构造函数 调用复制构造函数 调用无参构造函数 box0:0 box0:0 无名:1