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、模板及智能指针
//智能指针包装了其他对象指针,对象指针可以是任何类型,它由模板类的参数指定
//智能指针在COM客户端广泛使用,用来自动管理引用计数

#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] = '\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] = '\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

时间: 2024-10-30 10:29:35

C++关键知识的相关文章

iOS之UI--通讯录的实例关键知识技术点积累

通讯录的实例关键知识技术点积累 效果展示: *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: point

2 js的20/80关键知识

1. 2 var a = 1; undefined a 1 alert(a); undefined var b = true; var c = "Hi"; undefined alert(b); alert(c); undefined function foo(bar){ alert(bar); return bar; } undefined var z = foo("Hi"); undefined z "Hi" function foo(bar

NLPIR技术运用知识图谱技术应用于智能金融

在金融领域,NLP技术的作用主要在于自动从海量的宏观.行业.微观资讯中发现.分析并整合与各类决策相关的信息. 知识图谱在金融中有多项应用,首先通过信息检索技术获取相关文本,然后借语义分析技术从非结构化文本中提取结构化的信息,最后将这些信息加以提炼,并且使之关联到未来可能的发展趋势,从而为预测和决策提供有价值的及时信息. 智能金融应用是通过知识图谱相关技术从招股书.年报.公司公告.券商研究报告.新闻等半结构化表格和非结构化文本数据中批量自动抽取公司的股东.子公司.供应商.客户.合作伙伴.竞争对手等

NLPIR搭建行业知识图谱实现智能客服应用

近几年,随着人工智能技术的深入发展及在各行各业加快落地化部署,客服行业已逐渐成为了人工智能技术众多落地应用中的重点应用场景.不少企业已经采用了智能客服机器人来替代大部分人工客服,并组建了智能化客服系统,由原来的大量人工客服模式转变为智能客服机器人+少量人工客服模式.智能客服机器人能全渠道连接客户,覆盖与客户接触的各类渠道,支持网页.QQ.H5.APP.微信公众号.微博等在线沟通,具备PC端和移动端全面接入能力,全方位连接并随时响应客户沟通需求.智能客服特点:24小时秒级响应,自动化智能回复解答客

NLPIR系统构建知识图谱助力智能客服服务

目前,市场上的智能客服机器人已经是一款成熟的SASS产品,90%以上的企业都可以直接接入,数据保存在云端或者机器人公司的数据库,部署非常方便.同时,对于一些大型集团公司或者金融类企业,对数据保密性要求比较高的,也可以实施落地化部署,所有数据均存放在企业本地服务器上. 智能客服机器人的应用场景有哪些寒暄闲聊,有趣互动丰富的寒暄语库,贴合业务场景,模拟真人对话亲切自然. 意向初筛,精准分流机器人通过消息过滤实现客户意向捕捉,精准分流并触发人工服务,通过高效率的问答处理,过滤出更有价值的高净值用户.

KGB知识图谱在智能问答方向发挥技术特色

智能问答即给定自然语言问题,通过对问题进行语义理解和解析,进而利用知识库进行查询.推理得出答案.与对话系统.对话机器人的交互式对话不同,智能问答具有以下特点:答案:回答的答案是知识库中的实体或实体关系,或者no-answer(即该问题在KB中找不到答案),当然这里答案不一定唯一,比如 中国的城市有哪些 .而对话系统则回复的是自然语言句子,有时甚至需要考虑上下文语境.评价标准:召回率 (Recall),精确率 (Precision) ,F1-Score.而对话系统的评价标准以人工评价为主,以及BL

程序员必读书单

作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文地址:http://www.cnblogs.com/figure9/p/developer-reading-list.html 关于 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及延伸阅读.旨在成为最好最全面的程序员必读书单. 前言 Reading makes a full man; conference a ready man; and writing

非计算机专业基础重点

编译原理你可以不看,这个课程理论性质的内容比较多,学完一遍收获也不会很大的.但是数据结构,有时间的话,应该看一下,要结合java的集合类的源码来看,这样效果最好的. 我觉得一个计算机专业的学生,读过jdk源码的人,估计不会超过5%,我让你们读源码不是因为计算机学生都必须读源码的,只是我对你们的要求高,才让你们读源码的. 笔试的内容一般涉及基本的网络知识,数据结构知识,操作系统知识,还有java技术知识,这个到时候我给你们找些题目,你们看看就行了,最主要是java技术知识,这个是最关键的,你们先抓

什么在推动SOA和应用程序现代化

听从了一些行业分析师的劝告,一些机构正在争先恐后地采用SOA.Web服务和其它应用程序整合或者应用程序现代化技术. 然而,这种做法显然是太乐观了.事实上,一些机构不需要那样着急地采用现代化项目.有长期经验的IT人员称,在许多机构,应用程序现代化是一种不得已的最后措施,只有在许可证.维护.技术支持或者平台成本高的无法承受时才采用.IT部门正在现代化比较老的应用程序(或者完全转换这些应用程序)以缓解风险,如程序员.操作员或者与这个业务有关的技术支持人员即将退休可能出现的风险. 在上述两种情况下,IT