首页 > 代码库 > C++关键知识

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

C++关键知识