• C++关键知识


    《精通MFC》第一章节整理复习
    //c++编程技术要点
    
    
    /*
    //1、虚函数及多态的实现
    //演示多态技术
    
    
    #include <iostream>
    using namespace std;
    
    void Demo();
    
    int main()
    {
    	Demo();
    	getchar();
    
    	return 0;
    }
    
    class Graphic
    {
    public:
    	virtual void Draw();
    }; //END CLASS DEFINITION Graphic
    
    void Graphic::Draw()
    {
    	cout<<"绘制Graphic"<<endl;
    }
    
    class Line: public Graphic
    {
    public:
    	virtual void Draw();
    }; //END CLASS DEFINITION Line
    
    void Line::Draw()
    {
    	cout<<"绘制Line"<<endl;
    }
    
    class Rect: public Graphic
    {
    public:
    	virtual void Draw();
    }; //END CLASS DEFINITION Rect
    
    void Rect::Draw()
    {
    	cout<<"绘制Rect"<<endl;
    }
    
    class Text: public Graphic
    {
    public:
    	virtual void Draw();
    }; //END CLASS DEFINITION Text
    
    void Text::Draw()
    {
    	cout<<"绘制Text"<<endl;
    }
    
    void Demo()
    {
    	Graphic *g[3];
    
    	Line line;
    	Rect rect;
    	Text text;
    	
    	g[0] = &line;
    	g[1] = ▭
    	g[2] = &text;
    
    	for(int i = 0; i < 3; i++)
    	{
    		g[i]->Draw();
    	}
    	cout<<endl;
    
    } 
    */
    
    ///////////////////////////////////////////////////////////////////////////
    
    //2、动态调用
    //首先我们要知道。编译器会为每个有虚函数的类创建一个虚函数表,所以该类对象实例在内存中的
    //布局分为两部分,第一部分为4字节,指向虚函数表的指针,剩下的部分是对象的数据。
    //sizeof运算符包括指向虚函数表的指针的4个字节长度
    
    /*
    #include <iostream>
    using namespace std;
    
    void Demo1();
    void Demo2();
    
    int main()
    {
    	//Demo1();
    	Demo2();
    
    	return 0;
    }
    
    class V1
    {
    private:
    	int Size;
    	
    public:
    	int Size2;
    
    	V1();
    	~V1();
    	void DoShow();
    	virtual void Show();
    };
    
    V1::V1()
    {
    	Size = 5;
    	Size2 = 10;
    }
    
    V1::~V1()
    {
    	Size = 0;
    	Size2 = 0;
    }
    
    void V1::DoShow()
    {
    	cout<<"Size2: "<<Size2<<endl;
    }
    
    void V1::Show()
    {
    	cout<<"Size: "<<Size<<endl;
    }
    
    void Demo1()
    {
    	//动态调用,用一个void *类型指针来调用实例对象
    	void *pObjt = NULL;
    	V1 v1;
    
    	int len = sizeof(V1);
    	cout<<"len: "<<len<<endl;
    	pObjt = new char[len];
    
    	*(int *)pObjt = *(int *)&v1;  //①
    
    	//这样的拷贝方式是浅拷贝。假设V1中包括指针。则仅拷贝指针本身而不拷贝批针所指的内容,
    	//若想使用深拷贝,则须要在类定义中重载"="运算符,
    	//这里的赋值操作仅仅会拷贝对象的数据,而不会复制指向虚函数表的指针
    	*(V1 *)pObjt = v1;
    
    	((V1 *)pObjt)->DoShow();  
    	((V1 *)pObjt)->Show();  //②
    	
    	//释放内存:先显示调用目标类的析构函数。释放对象的内存资源。然后delete为指针pObjt所分配的内存
    	((V1 *)pObjt)->~V1(); //释放对象资源
    	delete pObjt;	//释放指针所指向的资源
    	pObjt = NULL; //将指针置空
    
    	getchar();
    }
    //对于非虚函数的调用。不要设置虚函数表指针就能够调用了(即上面的①和②能够同一时候删除。也不会出错)。但如
    //果调用了虚函数,则必须保证pObjt所指的内存的前4个字节正确指向了目标类的虚函数表。

    //一般非常少用void *指针直接动态调用,而是声明一个跟目标类内存布局兼容的结构,该结构的前4个字节为DWORD_PTR //用来指高目标类的虚函数表,结构后面的是一系列的数据或成员声明(我们都知道函数是不占用内存的),且要保证结构 //的数据成员集合为目标类中数据成员集合的超集,并要求它们公共的部分排列一致。 //以下用结构体来取代void *类型指针 struct V2 { int m_vtbl; //虚函数表指针占位符 int size21; int size22; //后面的数据或成员都没有什么用 void MyShow(){} int size23; }; void Demo2() { V1 v1; V2 v2; v2.m_vtbl = *(int *)&v1; *(V1 *)&v2 = v1; ((V1 *)&v2)->DoShow(); ((V1 *)&v2)->Show(); getchar(); } */ /* //3、接口技术 //接口是一种特殊的抽象类,它的全部成员都是纯虚函数。且不包括不论什么的数据成员。这样指向接口的指针 //仅是一个指向虚函数表的指针,而不会有不论什么的数据,接口的虚函数指针将被拷贝到子类。子类负责实现 //这些虚函数 //一个类向它的友元类公开全部的数据和方法。

    包括公有的。私有的和受保护的。

    //接口演示,对COM框架的模拟 #include <iostream> using namespace std; void Demo(); int main() { Demo(); return 0; } //定义两个接口。当中IHello接口从IUnknown接口继承 class IUnknown { public: virtual void *QueryInterface(int IID) = 0; virtual void AddRef() = 0; virtual void Release() = 0; }; //END INTERFACE DEFINITION IUnknown class IHello: public IUnknown { public: virtual void Hello(char *szMsg) = 0; }; //END INTERFACE DEFINITION IUnknown #define IID_IUnknown 1 #define IID_IHello 2 int CLASID_CAT; //提前声明友类。訪问CAT类的私有构造函数 class Factory; //抽象基类 class HelloImplement: IHello { private: int m_nRef; protected: HelloImplement(); public: void *QueryInterface(int IID); void AddRef(); void Release(); virtual void Hello(char *szMsg) = 0; }; //基于引用计数的生存期管理 HelloImplement::HelloImplement() { m_nRef = 0; } void HelloImplement::AddRef() { m_nRef++; } void HelloImplement::Release() { m_nRef--; if (m_nRef == 0) { delete this; } } //接口查询 void *HelloImplement::QueryInterface(int IID) { if (IID == IID_IUnknown) { AddRef(); return (IUnknown *)this; } if (IID == IID_IHello) { AddRef(); return (IHello *)this; } return NULL; } //详细类 class Cat: public HelloImplement { private: char *m_szName; public: void Hello(char *szMsg); private: Cat(char *name); friend class Factory; //友元类 }; Cat::Cat(char *name) { int len = strlen(name); m_szName = new char[len + 1]; strcpy(m_szName, name); } void Cat::Hello(char *szMsg) { cout<<"m_szName: "<<m_szName<<endl; cout<<"szMsg: "<<szMsg<<endl; } //类工厂。创建对象实例 class Factory { public: static void *GetComObject(int CLASID); }; void *Factory::GetComObject(int CLASID) { if (CLASID == CLASID_CAT) { Cat *cat = new Cat("小猫"); //返回对象的IUnknown接口 return cat->QueryInterface(IID_IUnknown); } return NULL; } //演示接口 void Demo() { IUnknown *pIUnknown = (IUnknown *)Factory::GetComObject(CLASID_CAT); //查询其它接口 IHello *pIHello = (IHello *)pIUnknown->QueryInterface(IID_IHello); //释放接口 pIUnknown->Release(); pIHello->Hello("演示接口"); //释放接口 pIHello->Release(); getchar(); } //把类的构造函数声明为私有的来防止直接构造事实上例。

    //假设对象实现了某个接口,则对象能够转化为接口指针 */ /* //4、模板及智能指针 //智能指针包装了其它对象指针,对象指针能够是不论什么类型,它由模板类的參数指定 //智能指针在COMclient广泛使用,用来自己主动管理引用计数 #include <iostream> using namespace std; void Demo(); int main() { Demo(); return 0; } class RefCount { private: int crefs; public: RefCount(); ~RefCount(); void upCount(); void downCount(); }; RefCount::RefCount() { crefs = 0; } RefCount::~RefCount() { cout<<"再见! "<<crefs<<endl; } void RefCount::upCount() { crefs++; cout<<"计数添加到: "<<crefs<<endl; } void RefCount::downCount() { crefs--; if (crefs == 0) { delete this; } else { cout<<"计数降低到: "<<crefs<<endl; } } class Sample:public RefCount { public: void doSomething(); }; void Sample::doSomething() { cout<<"做一些事情!"<<endl; } //用模板类来实现智能指针 template<class T> class Ptr { private: //内包括的对象指针,指针类型由模板參数指定 T *p; public: Ptr(T *p_):p(p_)//设置内部指针 { //添加计数 p->upCount(); } //析构函数降低计数 ~Ptr() { p->downCount(); } //运算符重载 //重载类型转换符 operator T*(void) { return p; } //*重载 T &operator *(void) { return *p; } //->重载 T *operator->(void) { return p; } //=重载 //原来指向的计数减1,新指向的对象的计数加1:引用计数的基本原则 Ptr & operator=(T *p_) { p->downCount(); p = p_; p->upCount(); return *this; } //=重载 Ptr & operator=(Ptr<T> &p_) { return operator = ((T *)p_); } }; //演示表示智能指针的模板类 void Demo() { Ptr<Sample> p = new Sample; Ptr<Sample> p2 = new Sample; p = p2; //p的引用计数将自己主动变为0。并会自己主动销毁 p->doSomething(); //利用*操作符调用 (*p2).doSomething(); //利用T *操作符调用 ((Sample *)p)->doSomething(); return ; //p2和p超过范围。析构函数将被调用,从而downCount也被调用 //p2将被销毁 } */ /* //5、重载 //一般而言。重载有以下几种使用方法: //(1)在同一个类中定义多个同名的方法。这些方法具有不同的參数列表 //(2)子类重写父类的虚方法 //(3)子类重写父类的非虚方法(覆盖) //以下演示运算符重载 #include <iostream> #include <cassert> using namespace std; void Demo(); int main() { Demo(); return 0; } class String { private: char *m_buffer; public: //构造函数 String(){m_buffer = NULL;} String(char *string); String(String *str); String(String &str); ~String(){delete m_buffer;} //运算符重载 String &operator=(char *string); String &operator=(String &string); String operator+(char *string); String operator+(String &string); char &operator[](int); operator char*(){return m_buffer;} bool operator==(char *string); bool operator==(String &string); String &operator+=(char *string); String &operator+=(String &string); int Length(){return strlen(m_buffer);} }; String::String(char *string) { if (string == NULL) { m_buffer = NULL; return; } size_t len; len = strlen(string); m_buffer = new char[len+1]; strcpy(m_buffer, string); } String::String(String &string) { char *str = (char *)string; if (str == NULL) { m_buffer = NULL; return; } size_t len = strlen(str); m_buffer = new char[len + 1]; strcpy(m_buffer, str); } String &String::operator=(char *string) { if (string == NULL) { delete this; m_buffer = NULL; return *this; } if (m_buffer != NULL) { delete m_buffer; } int len = strlen(string); m_buffer = new char[len + 1]; strcpy(m_buffer, string); return *this; } String &String::operator=(String &string) { return operator=((char *)string); } String String::operator+(char *string) { if (string == NULL) { return *this; } String temp; if (m_buffer == NULL) { temp = string; return temp; } size_t len = strlen(m_buffer) + strlen(string); char *ch = new char[len + 1]; ch[0] = ''; strcat(ch, m_buffer); strcat(ch, string); temp = ch; return temp; } String String::operator+(String &string) { return operator+((char *)string); } char &String::operator[](int i) { size_t len = strlen(m_buffer); assert(i>=0 && i<len); return m_buffer[i]; } bool String::operator==(char *string) { if (m_buffer == NULL) { if (string == NULL) { return true; } return false; } if (string == NULL) { return false; } return strcmp(m_buffer, string)==0; } bool String::operator==(String &string) { return operator==((char *)string); } String &String::operator+=(char *string) { if (string == NULL) { return *this; } if (m_buffer == NULL) { *this = string; return *this; } size_t len = strlen(m_buffer) + strlen(string); char *ch = new char[len + 1]; ch[0] = ''; strcat(ch, m_buffer); strcat(ch, string); m_buffer = ch; return *this; } String &String::operator+=(String &string) { return operator+=((char *)string); } void Demo() { String str1("xiao hua"); String str2("yan yang"); cout<<(char *)str1<<endl; for (int i = 0; i < str2.Length(); i++) { cout<<str2[i]; } cout<<endl; if (str1 == str2) { cout<<"str1与str2相等!"<<endl; } else { cout<<"str1与str2不相等!"<<endl; } String str3 = str1 + str2; cout<<(char *)str3<<endl; str3 += str1; cout<<(char *)str3<<endl; getchar(); } //一元操作符的重载函数没有參数 //二元操作符的重载有一个參数 //运算符的第一个操作參数总是当前对象this //自增的自减运算符的重载 //(1)前置++或-- //重载格式: operator++或operator-- //(2)后置++或-- //重载格式: operator++(int)或operator--(int) */


    作者:http://blog.csdn.net/lp310018931

  • 相关阅读:
    计算一路话音消耗的带宽
    谋哥:我跟CEO们都说了啥
    wchar与char字符转换的探究
    pl/sql配置连接远程数据库oracle,本地没有安装oracle数据库的情况下
    围住浮动元素的三种方法
    Chromium浏览器组件设计意图
    tonymillion/Reachability的使用
    赵雅智_名片夹(3)_下拉刷新载入很多其它
    动态创建菜单和动态关联菜单项事件
    delphi创建动态菜单
  • 原文地址:https://www.cnblogs.com/llguanli/p/6957626.html
Copyright © 2020-2023  润新知