析构函数

绘图、GDI、颜色及字体

旧街凉风 提交于 2020-01-01 01:28:51
1,任何时候当程序需要直接在屏幕或打印机上绘图的时候,都需要调用GDI函数,GDI函数包含了一些用于绘制图形、位图以及文本的函数。 2,Windows的设备环境是GDI的关键元素,它代表了物理设备。每一个C++设备环境对象都有与之对应的Windows设备环境, 并且通过一个32位类型的HDC句柄来标识。 3,MFC库设备环境类基类CDC包含了绘图所需要的所有成员函数,并且几乎所有派生类只有构造函数和析构函数不同(CMetaFileDC类除外)。 对于显示器来说,常用的派生类有CClientDC 和 CWindowDC,而对其它设备(如打印机或内存缓冲区),则可以构造一个基类CDC的对象。 对于显示器和打印机设备环境对象来说,应用程序框架会直接将句柄附在对象上;而对其它设备环境(如内存设备环境), 为了将对象与句柄相联系,在构造完对象之后,还必须调用一个成员函数(进行初试化)。 4,CClientDC类 和 CWindowDC类 如果构造CClientDC对象,则设备环境的映射区域限于客户区域,不能在客户区域外绘图。原点(0,0)在客户区左上角。 如果创建CWindowDC对象,则设备环境的映射区域为整个窗口(包括标题栏、状态栏、窗口边框等)。原点(0,0)在整个窗口的左上角。 注意: 1)视图窗口没有非客户区域. 2)视图窗口覆盖在框架窗口之上。 3)在《》中的内容

数据类型,数组,构造函数,析构函数,重载与重写,类,接口

霸气de小男生 提交于 2019-12-31 10:12:02
编程语言中为什么要区分数据类型? 基于存储空间和运算速度的考虑,都定义为容量最大的,耗费的存储空间自然要大许多,小程序不明显,程序规模大的话,这就是问题了,再者,容量大的数据运算起来自然就慢,同样,程序规模大的话,运算速度明显受到影响 数组是什么? 是否可以作为一种数据类型? 数组,是有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。 组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。 用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按无序的形式组织起来的一种形式。 这些无序排列的同类数据元素的集合称为数组。 数组是用于储存多个相同类型数据的集合。 类的构造函数和析构函数,有什么关系,分别是如何使用的 构造函数的作用:用于新建对象的初始化工作。 析构函数的作用:用于在撤销对象前,完成一些清理工作,比如:释放内存等。 每当创建对象时,需要添加初始化代码时,则需要定义自己的构造函数;而对象撤销时,需要自己添加清理工作的代码时,则需要定义自己的析构函数。 方法重载与重写的概念,区别 重载:是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,最常见的重载的例子就是类的构造函数。 重写:是子类的方法覆盖父类的方法,要求方法名和参数都相同 类是属性的抽象

C++构造函数、析构函数与抛出异常

陌路散爱 提交于 2019-12-29 17:28:37
【本文链接】 http://www.cnblogs.com/hellogiser/p/constructor-destructor-exceptions.html 【问题】 构造函数可以抛出异常么?析构函数可以吗? 【分析】 从语法上来说,构造函数和析构函数都可以抛出异常。但从逻辑上和风险控制上,构造函数可以,析构函数不推荐抛出异常。 (1)构造函数可以抛出异常 无论何时,从构造函数中抛出异常都是可以的。动态创建对象要进行两个操作:分配内存和调用构造函数。若在分配内存时出错,会抛出bad_alloc异常;若在调用构造函数初始化时出错,会不会存在内存泄漏呢?答案是不会。 new运算符保证不会出现内存泄漏: C++ Code 1 T *p = new T; 将被编译器转换给类似下面的样子: C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 void allocate_and_construct() { // 第一步,分配原始内存,若失败则抛出bad_alloc异常 try { // 第二步,调用构造函数构造对象 new (p)T; // placement new: 只调用T的构造函数 } catch (...) { delete p; // 释放第一步分配的内存 throw ; // 重抛异常,通知应用程序 } } (2)析构函数不推荐抛出异常

C++异常注意事项

梦想的初衷 提交于 2019-12-29 09:10:29
C++里面catch对于类型转换,限制比参数传递时候要多: 不可以进行 标准算术转换 和 类的自定义转换 :在函数参数匹配的过程中,可以进行很多的类型转换。但是在异常匹配的过程中,转换的规则要严厉。 标准算术转换,指的是 short转成int 等等。异常catch的时候,不允许转换,指的是匹配的时候,就不会匹配上。比如下面: #include <iostream> #include <exception> #include <stack> using namespace std; int main() { std::cout << "Hello, World!" << std::endl; stack<int> stk; //stk.push(5); try { //stk.pop(); short s = 5; throw s; } /*catch(runtime_error exception1) { std::cout << exception1.what() << endl; }*/ catch(int &x) { std::cout << x << endl; } catch (...) { cout << "here catch" << endl; } return 0; } View Code 输出: here catch View Code 意味着

c++异常总结

三世轮回 提交于 2019-12-29 05:21:06
堆栈辗转开解(stack-unwinding): 如果一个函数中出现异常,在当前函数内即通过 try..catch 捕捉(且捕捉到)的话,可以继续往下执行;如果不捕捉(或未捕捉到)就会抛出(与通过 throw 显式抛出效果相同)到外层函数,则当前函数会终止运行,释放当前函数内的局部对象(局部对象的析构函数就自然被调用了),外层函数如果也没有捕捉到的话,会再次抛出到更外层的函数,该外层函数也会退出,释放其局部对象……如此一直循环下去,直到找到匹配的 catch 子句,如果找到 main 函数中仍找不到,则调用名为 terminate 的标准库函数,该函数在 exception 头文件中定义,导致程序非正常退出。可以通过 std::set_terminate(fun) 来指定 terminate 调用的函数来输出一些信息。 异常是通过抛出对象而引发的,抛出的对象类型决定应该激活哪个处理代码 ,被选中的处理代码是距离抛出异常最近的匹配的 catch 子句。 #include <iostream> #include <string> void fun1() { throw "this is char* exception"; } void fun2() { throw std::string("this is string exception"); } int main() { try {

c++抛出异常与栈展开(stack unwinding)

旧城冷巷雨未停 提交于 2019-12-29 05:20:02
  抛出异常时,将暂停当前函数的执行,开始查找匹配的catch子句。首先检查throw本身是否在try块内部,如果是,检查与该try相关的catch子句,看是否可以处理该异常。如果不能处理,就退出当前函数,并且释放当前函数的内存并销毁局部对象,继续到上层的调用函数中查找,直到找到一个可以处理该异常的catch。这个过程称为 栈展开( stack unwinding) 。当处理该异常的catch结束之后,紧接着该catch之后的点继续执行。 1. 为局部对象调用析构函数 如上所述,在栈展开的过程中,会释放局部对象所占用的内存并运行类类型局部对象的析构函数。但需要注意的是,如果一个块通过new动态分配内存,并且在释放该资源之前发生异常,该块因异常而退出,那么在栈展开期间不会释放该资源,编译器不会删除该指针,这样就会造成内存泄露。 2. 析构函数应该从不抛出异常 在为某个异常进行栈展开的时候,析构函数如果又抛出自己的未经处理的另一个异常,将会导致调用标准库terminate函数。通常terminate函数将调用abort函数,导致程序的非正常退出。所以析构函数应该从不抛出异常。 3. 异常与构造函数 如果在构造函数对象时发生异常,此时该对象可能只是被部分构造,要保证能够适当的撤销这些已构造的成员。 4. 未捕获的异常将会终止程序 不能不处理异常。如果找不到匹配的catch

寒假学习笔记(3)

烂漫一生 提交于 2019-12-29 04:50:34
2018.2.9 类 class class 类名{};类似与结构体; 类的实质是一种数据类型,类似于int、char等基本类型,不同的是它是一种复杂的数据类型。因为它的本质是类型,而不是数据,所以不存在于内存中,不能被直接操作,只有被实例化为对象时,才会变得可操作。 使用类的成员变量和成员函数: 对象名.成员名; 指针->成员名; 引用名.成员名; 类的内部封装了方法,用于操作自身的成员。类是对某种对象的定义,具有行为(be-havior),它描述一个对象能够做什么以及做的方法(method),它们是可以对这个对象进行操作的程序和过程。它包含有关对象行为方式的信息,包括它的名称、方法、属性和事件; 标识符: private: 私有成员,只能在成员函数内访问。; public : 公有成员,可以在任何地方访问; protected: 保护成员,只可以在成员函数和其的子类中访问; 由类定义的称为对象; 在类的成员函数以外的地方,只能够访问该类对象的公有成员,不能将类完全封装,这样就失去了意义; 构造函数与析构函数与普通函数的区别 函数名固定:构造函数和析构函数的函数名必须是类名。 声明格式不同: - 构造函数和析构函数没有返回值,连空返回值——void也没有。 - 构造函数的声明形式:类名(参数列表); - 析构函数的声明形式:~类名(); 重载的特殊性

4-构造函数与析构函数

♀尐吖头ヾ 提交于 2019-12-29 04:48:43
//返回值问题 char *Add(char a, char b) { //分配 char *p = new char[2]; //strcpy strcpy(p, &a); //不能使用+ return strcat(p, &b); } string Add(string a, string b) { //1.连接方式 //2.append return a.append(b); } 回顾: 1.类?方法?属性? 2.定义类 3.定义数据成员+成员函数 4.构建对象+初始化对象 ------------------------------------------------------------- 构建对象的过程:调用构造函数 构造函数:初始化基本成员 调用方式:系统调用 定义形式: 类名(参数列表){函数语句}; 可重载 可缺省参数 注意点: 1.函数名与类名一致 2.函数没有返回值 3.有一个默认的构造,如果你写了构造函数,默认的构造没有了 4.构造函数只能是public属性 5.不能够自己调用 析构函数:释放构建对象的过程动态申请内存 定义形式: ~类名() 不可以重载 没有参数 存在默认构造函数 注意点: 1.函数名与类型一致 2.函数没有返回值 3.没有参数 4.不能重载 5.对象作用结束后 拷贝构造函数:实现一个对象给另一个对象初始化 (默认的构造函数) 定义方式:

JAVA与C++区别(一)

别说谁变了你拦得住时间么 提交于 2019-12-28 19:38:33
首先,引用一句Thinking in java中作者一直在强调的一句话:一切皆对象。 本文主要关于C++和JAVA类及一些其他关键概念的区别:   在OO编程中几个关键概念无非是类,封装,继承,多态。 一:关于类 (1):在C++中定义类: class User { public:   Uers(string str,int yy){ name=str,age=yy;}   void print(){ ...... } private     string name;   int age;   };      // 类的结尾处应该以“;”结束 在C++中有两种初始方式:   User u("zhangsan",20);          //(A)   User *p=new User("zhangsan",20);     //(B) 在A中,构造函数创建了变量u,它在堆栈上为新的对象分配内存。当u离开它的作用域的时候,它的内存自动释放。 在B中,操作符new在堆上为新的对象分配内存,并返回一个指向该块内存的指针,这块内存可由delete操作符显示的进行释放:delete p;(当我们在指向一个类类型的对象的指针上使用delete时,delete操作符将会调用这类的析构函数)。 在C++中,“.”和“->”操作符成为成员访问符:u.print();                

动态内存与智能指针

*爱你&永不变心* 提交于 2019-12-27 21:37:11
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 前言 1.生命周期 全局对象: 程序启动时分配,程序结束时销毁 局部自动对象: 执行流进入其定义的块时分配,执行流退出其定义的块时销毁 局部static对象: 程序启动时分配(但在其定义的块或作用域内起作用),程序结束时销毁 动态分配的对象: 生命周期与创建地点无关,只有当显示的被释放时,才会被销毁 智能指针:标准库定义,用于管理动态分配的内存,当一个对象应该被释放时,指向它的智能指针可以确保自动的释放它 2.内存分类 静态内存: 用于存储局部static对象、类的static数据成员、全局变量 栈内存: 用于存储局部非static对象 堆内存(内存池): 用于存储动态分配的对象——动态分配的对象,其生命周期由程序控制,例如使用new或delete 3.动态内存 动态内存使用过程中容易产生的问题 内存泄露: 使用后忘记释放内存 引用非法内存: 在尚有指针引用内存的情况下就释放它 使用动态内存的原因: 程序不知道自己需要使用多少对象 程序不知道所需对象的准确类型 程序需要在多个对象间共享底层数据——若两个对象共享底层数据,当某个对象销毁时,我们不能单方面的销毁底层数据 4.智能指针 智能指针和常规指针直接的区别:智能指针能够自动释放所指向的内存(类似java中的垃圾回收机制),而常规指针不能。