<C++ - 构造和析构> 2018-01-10
/* 回顾上节的内容: 1.实现中的事情 物 ->类 <属性 -> 成员变量> <行为 -> 成员函数> 2.访问权限 public private (protected:受保护的) 函数 公有 成员 私有 公有可以在类外访问 私有 只能类内访问 3.struct 和class区别: 结构体就是公有的类 类就是私有的结构体 -->this 指针 指向对象本身 在成员函数中 可以在成员函数中访问成员变量或者是调用其他成员函数(在类外不能使用) 新知识点: 1.构造 析构函数 1.1 构造函数 成员变量 私有 只能用类里面的函数赋值 构造函数 定义一个对象的时候 同时给他初始化 构造函数有时候也叫做: 构造器 函数名和类名相同 没有返回值 也不需要要调用(对象定义的时候自动调用 并且只调用一次) 构造函数 可以重载 可以缺省(注意二义性) 构造自己调用 定义对象 对象后面没有() -->无参构造 对象后面有() 调用有参构造 定义对象的时候同时会调用构造函数 不写构造函数的时候 定义对象的时候会不会调用构造函数 (会调用) 没写 编译器会给一个默认构造(没有参数 没有执行任何功能)不做任何事情 如果说你写了一个构造函数 编译器就不会给这个构造函数 2.1析构函数 作用 析构 释放对象占用内存 没有返回值 没有参数 函数名就是类名前面加上一个 ~ 析构 对象声命周期结束之后自动调用 如果没有写析构 编译器会分配一个默认析构(不做任何事情) 构造 释放 内存(构造中申请内存 析构中释放) 释放的是对象内部申请的内存 2.new delete 2.1 new 和 delete会调用对象的构造和析构 malloc 和 free不会 2.2 delete 如果是数组的话 那么加上[] (不加就不会调用每个对象的析构函数) 答疑课部分 3.命令行参数 指 main 的参数 int argc char*argv[] // _TCHAR*argv[] (多字节) argc 表示后面的指针数组的指针的个数 数组大小 agrv 指向多个字符串(传入的参数) 传递参数: 1.拖动exe到cmd窗口 空格隔开 手动输入参数 2.拖动文件到exe上 argv[0] --> 一定是exe路径 首先清楚 参数 -->根据参数写代码就可以了 */ #include <iostream> using namespace std; //====================================类函数======================================== class sunmer { private: // 私有成员不能在类外访问 int x; // 只是说明类中有哪些成员 不赋值 double y; public: // 无参数构造 sunmer() // 可以有参数 也可以没有参数 可以重载 { cout << "调用的是无参构造函数" << endl; x = 0; y = 0; } sunmer(int x, double y) // 有参数构造 { cout << "调用的是有参构造函数2" << endl; this->x = x; this->y = y; } sunmer(double y, int x = 0) // 缺省的构造函数 { cout << "调用的是缺省函数" << endl; this->x = x; this->y = y; } void play() { cout << "play well" << endl; } void setSummer() { //cin >> x >> y; cin >> this->x >> this->y; } void setSummer(sunmer&temp) // 这个传递一个参数 (2) { temp.x = 2; this->x = 3; } void print() { cout << x << "\t" << y << endl; } }; /** 类 -->抽象 成员赋值方式: 1.构造函数 定义对象的时候给他赋值 2.定义其他函数 后面用对象调用给他赋值 */ class student { int x; public: student(int x) // 有参数 { cout << "调用构造函数" << endl; this->x = x; } /*student() { }*/ ~student() // 析构函数 1.可以重载不? 2.可以缺省不? (没有参数 不能重载 缺省是给参数赋值默认值 没办法缺省) { cout << "调用析构函数" << endl; } }; int main() { #if 0 sunmer seven,six; // 定义一个seven对象 sunmer ou(3, 2.15); // 调用有参数构造 参数可以是变量 sunmer danny(2); // 调用缺省构造函数 ou.print(); getchar(); seven.setSummer(six); // 调用(2)行的函数 /** temp.x ->相当等于: six.x thix->x ->相对等于: seven.x */ seven.play(); //函数调用的时候记得加括号 seven.setSummer(); // 输入数据 seven.print(); // 打印数据 #elif 0 //student bug; // 不写() 调用默认(无参)构造 // 错误 不存在默认构造函数 解决方案1 自己写一个没有参数的构造函数 // 解决方案2 调用有参构造函数 写参数 //student arr[10]; // 定义类数组 对象没办法传递参数 -->调用无参构造 // 用堆内存申请类的动态数组 //student *p = new student(1); #elif1 #endif // 析构函数 { // 生命周期 student danny(1); } getchar(); return 0; } /* 作业: 改写我们上次作业 用构造函数给他赋值(成员变量 换成私有属性) */
02、MySring(实例)
#include <iostream> #include <cstring> #include <cstdlib> using namespace std; class myString // 动态存放放字符串 用的是堆内存 { private: char *str; // 指针 int size; // 堆内存大小 int lenth; // 字符串长度 public: myString() // 构造 1.没有放回值 2.什么时候调用 { cout << "调用无参构造" << endl; str = NULL; size = 0; lenth = 0; } myString(char arr[]) // 传入字符串 { lenth = strlen(arr); // 先保留字符串的长度 this->size = lenth + 1; // 多申请一点空间 str = new char[this->size]; // 申请内存 strcpy(str, arr); // 拷贝字符串 } ~myString() // 析构函数: 1.没有返回值 2.没有参数 3.对象生命周期结束之后自动调用一次 { cout << "调用析构函数" << endl; //delete[]str; // 释放申请的内存 (这样会报错) if (str != NULL) { delete[]str; // 释放申请的内存 str = NULL; size = 0; lenth = 0; } } }; int main() { #if 0 // 析构函数的例子 myString danny("郑磊"); // 释放str指向的这块内存 不是danny的这块内存 danny.~myString(); // 析构可以手动调用 #endif /** new delete(会调用构造) delete(会调用析构) malloc free 直接申请/释放内存 不会调用构造析构 */ //myString *p = new myString[4]; // 申请内存 //delete[]p; // (释放内存) 如果不释放内存的话 内存泄漏 //delete p; // 如果有[] 会调用每个对象的析构函数 /* myString *p = new myString; delete p; */ myString *p = (myString*)malloc(sizeof(myString)* 4); // 这个没敢用 free(p); getchar(); return 0; }
03、测试
// 2018-01-10-测试.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) // 多字节 改多字节字符集 { printf("\n命令行参数\n"); // 测试 代码 打印命令行参数 for (int i = 0; i < argc; i++) { printf("%s\n", argv[i]); } getchar(); return 0; }