windows窗口
前言额总的来说c++的语法是又看了一遍~~猪脑子啊有些就是没记住。先看看windows的api,然后玩玩老的mfc先吧。
引用
微软开发文档文档地址
正文白天没起来,下午game了一会,然后又刷手机。
windows程序设计就是c++类的形式封装成windowsAPI,然后设计的应用程序框架。减少程序开发的工作量。
对于没有图形化的命令行界面,程序入口都在main函数而对于windows而言,它的入口在WinMain。
对于winmain的介绍,在没有引用文件下,可以去官方文档查看
1int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
hInstance 称为“实例句柄”或“模块句柄”。操作系统使用此值在内存中加载可执行文件时标识可执行文件 (EXE) 。 某些Windows函数需要实例句柄,例如加载图标或位图。
hPrevInstance 没有意义。 它在 16 位Windows中使用,但现在始终为零。
pCmdLine 包 ...
虚函数实现机制
前言虚函数本身就很玄学,像基类只做声明,派生类在定义,然后不同派生类之间还能依次找到不同的。
正文注:x86环境,非x64
1234567891011121314151617181920212223class AIM{public: int HP; virtual void Eat(){ std::cout << "AIM\n"; } virtual void Die(){ std::cout << "AIM-DIE\n"; }};class WOLF :public AIM{public: virtual void Eat(){ std::cout << "WOLF\n"; } virtual void Die(){ std::cout << "WOLF-DIE\n"; } void Sound(){ std::cout ...
类的成员函数的函数指针
前言函数指针:函数指针是指向函数的指针变量。
1234int add(int a,int b){ return a + b;}int (*pAdd)(int, int) = add;
正文12345678910class Box{public: void test(){ std::cout << "test!\n"; } void hhh(){ std::cout << "hhh!\n"; }};
如果按照正常逻辑,想让函数指针指向一个函数
1void (*pTest)() = test;
这样肯定是不对的,因为这个test是类的成员函数而不是所谓的全局函数,如果全局函数都没有,那么这个test就是一个未定义标识符有的人可能会想到作用域问题。
1void (*pTest)() = Box::test;
显然这也不是行的,毕竟类没有实例化,成员函数也非静态。成员函数最关键的是它内部可以调用this指针,这是普通的函数无法做 ...
抽象类
前言概念性的东西
正文纯虚函数像animal类,派生了dog和cat。animal中有一个函数move,只不过肯定是在派生类里面实现才有意义,毕竟不同动物类肯定有区别。virtual void move() = 0;
注:virtual写在返回值前后问题不大看个人习惯。毕竟他又不能作为返回值,写前面只是更加显眼一点
正常情况的虚函数virtual void move(){}或者virtual void move();,对于后者没有定义的话编译器一般都不会通过。在加上=0;之后就是我们所说的纯虚函数。
为什么要用纯虚函数,是因为基类虽然用不到,但是派生类难免会用到。
12345678910111213141516class animal{public: virtual void move();};class dog : public animal{public: void move(){}};int main(){ dog d1; return 0;}
像这种声明了,但是没有定义 ...
typeid
前言当指向类的指针转换好几次的时候,人为看过去雀食很累了,就可以用typeid去看这个变量的类型。
正文12345678910#include<iostream>int main(){ int a; std::cout << typeid(a).name(); return 0;}
最直接的情况
但是有个别变量的处理不是很好,比如long long
他显示的是__int64
还有的就是不是所有的编译器都默认打开这个功能。
检测多态类型指针类型12345class father{};class son : public father{};class grandson:public son{};
设计三个类
1234father *fa = new father();fa = new grandson();std::cout << typeid(fa).name();
看到返回的是类的指针类型,而不是正常的类型。因为需要解除引用,转出类型。
1234fath ...
虚函数dynamic_cast
引用dynamic_cast<type>()动态转换只支持方法多态类型的指针,如果转换成功返回指针,失败则返回nullptr同样分为两种情况:
向下转换 downcast
跨类转换 crosscast
注:不要随便转换this指针
还有一点,当dynamic_cast用于转换引用时,转换失败会抛出异常,所以一般不推荐转换引用
正文12345678910111213141516class father{public:};class son :public father{public:};class wolf :public son{};class pople :public son{};class werewolf :public wolf, public pople{};
还是之前的例子
1234son s1;father* fh = (father *)&s1;son *s2 = static_cast<son *>(fh);
正常情况下我们 ...
对象多态?
前言之前说了多态两种,一种对象多态,一种方法多态不过一般都是方法多态,也就是一个类中有虚函数。
正文至于对象多态表面现象也很简单,就是父类和子类之间可以相互转换。可以互相转化的原理是继承的时候,类在内存之中的表达形式。
现学所知类型转换
隐式类型转换
静态强制转换
动态强制转换
C语言风格就是:(type)这种阔号前置的强制转换类型c++风格的转换则是:static_cast<type>() 这样至于隐式转换,整型从小转大,浮点数也是从小到大,整型和浮点型运算,要转换成浮点型。
一切的前提是不加阔号进行人为干预
1234567891011121314151617class father{public:};class son :public father{public:};int main(){ father *fa; son s1; fa = &s1; return 0;}
单从类型上是对不上的,但是它发生了隐转,并且是类的向上转型。
1son *s1 = fa;
而此类操作,属于向下转型,本 ...
多态+虚函数的问题
前言自虚函数之后,多态会带来一些小问题
正文12345678910111213141516171819class father{public: int x; int y; virtual void Move(){ std::cout << "father move\n"; } void test(){ Move(); }};class son :public father{public: void Move() override{ std::cout << "son move\n"; }};
当我们实例化son,并且调用test的时候,这个test当然是继承过来的。
12son s1;s1.test();
第一感觉可能会以为输出father的move。但是,这个test是被继承过来的,son类中也有一个move函数,这个move是通过虚函数继承的,也就是说move只要在这个派生类中重写了,那么就不会跟基类的m ...
虚函数
前言关键字
virtual
正文123456789101112131415161718192021222324252627class MoveObject{public: int x; int y; void Move(){ x++; y++; }};class NPCObject :public MoveObject{public: void Move(){ x++; y++; std::cout << "NPCobject!\n"; }};class MonsterObject :public MoveObject{public: void Move(){ x++; y++; std::cout << "monsterobject!\n"; }};
在多态之前控制这种行为的时候,一般都是通过传入参数不同
1234567void move(NPCObject *obj) ...
多态
前言一个人,可以说他是只猴,也可以说他是哺乳动物,也可以说他是动物。但本质上就是个人。
正文
对象多态在前言之中,人可以推导是动物,但是动物不能百分百推断为人。
向上转型 父类=>子类
向下转型 子类=>父类
12345678910class animal{public: int age; int sex;};class pople :public animal{public: int money;};
可以看到这样转型编译器没有报错,但是实际上还是会发生内存切片的问题,毕竟子类继承之后多了属性,传给父类,就有一个地方无法表达。
编译器会给出提示。
内存切片,也就是我们此处,pople是有一个成员的,当由pople继承animal的类,然后实例化,那么其实已经有了三个成员,而animal本身就只有两个,所以用pople实例化的对象传给animal的时候那个多余的成员就很有可能会被抛弃掉。变量还能看得到,函数有的时候就不好说了。
像这样过不去的基本原因就是pople有三个成员内存多一块,而anima ...