C++编程关键路径(二)

第四章:开始学习C++

1、内联函数

声明为inline,它在调用点上被“内联”地展开,内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在调用处。

2、关于extern “C”

在c++语言中调用c库函数时,将c的函数用extern “C”声明,以确保c++程序中调用的c函数是用c语言的规则进行编译的,而不是用c++规则编译的,这样才能正确的调用到自定义c库函数。一般为:

#ifdef _cplusplus

Extern “C”

{

       #endif

       …

       #ifdef  _cplusplus

}

#endif

3、函数指针

函数声明为:void Invoke (char* s);

定义fp为指向函数Invoke的指针:void (*fp) (char* s);

通常用宏定义的方式来声明函数指针:typedef void (*FP) (char* s);

 

4、回调函数:

使用者自己定义一个函数,使用者自己实现,然后这个函数做为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。即是由别人的函数运行期间来回调你实现的函数。

通常是使用者在程序中调用一个系统函数,然后这个系统函数再回调只用者自己定义的一个函数。

 

第五章:C++类和继承

1、对象访问成员时,一般用.或->,当定义了一个类指针时,需要用->来访问类的成员。

2、静态成员

静态成员是类的所有对象中共享的成员,而不是某个对象的成员。

static成员函数没有this指针。

static成员函数不能被声明为const。

static成员函数也不能被声明为虚函数。

static成员函数可以直接访问所属类的static成员,但不能直接使用非static成员。

访问类的static成员,既可以通过对象来访问,也可通过类直接访问。

类成员函数(无论是static成员函数或非static成员函数)都可以直接访问static数据成员。访问方式有两种:object.static_var 或   classname::static_var;object.static_func() 或   classname::static_func()。

 

3、友元

在类中声明一个普通函数,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员。

 

5、构造函数和析构函数

(1)    构造函数可以重载,即一个类中可以有多个构造函数。

程序中不可以直接调用构造函数。

(2)    析构函数:一个类中只有一个析构函数,析构函数可以在类中被调用。

 

6、拷贝构造函数和赋值函数:

拷贝构造函数的作用是用一个已知的对象来初始化另一个同类的对象,在初始化的时候将一个已知对象的数据成员的值拷贝给另一个同类的对象。

格式为:<类名>::<类名>(const<类名>&<引用名>)

 

在含有指针数据成员的时候构建自己的拷贝构造函数。这时,若用默认的值拷贝的构造函数就会有两个对象的指针成员指向同一个地址。

类的赋值和拷贝构造函数必须同时设计,尽量用拷贝构造来代替赋值。

赋值的格式:<类名>&<类名>::operator=(const <类名>&<引用名>)

类的赋值就是把一个类对象赋值给另一个对象。

下面是在类含有指针数据成员的时候,的构造函数、拷贝构造函数和赋值函数示例:

class CTest
{
public:
	CTest(char* p)   //构造函数
	{
		if(p)
		{
			pData=new char[strlen(p)+1];
			strcpy(pData,p);
		}
		else
		{
			pData=new char[1];
			*pData='\0';
		}
	}

	CTest(const CTest& T)  //拷贝构造函数
	{
		if(T.pData)
		{
			pData=new char[strlen(T.pData)+1];
			strcpy(pData,T.pData);
		}
		else
		{
			pData=new char[1];
			*pData='\0';
		}
	}

	CTest& operator=(const CTest& T)  //赋值操作
	{
		if(this==&T)
		{
			return *this;
		}
		if(T.pData)
		{
			if(pData)
			{
				delete [] pData;
			}
			pData=new char[strlen(T.pData)+1];
			strcpy(pData,T.pData);
		}
		else
		{
			pData=new char[1];
			*pData='\0';
		}
		return *this;
	}

	~CTest()
	{
		delete* pData;
	}

	char* pData;
};

 

7、类的成员初始化表

跟在原型后面,由冒号开头,由逗号分割的成员、实参对,实参是括号中的初始值。

 

8、 继承,虚函数,重载,覆盖

用父类的指针调用子类的普通函数时,调用的是父类的函数。若调用的是虚函数(父类、子类都是虚函数)则随父类指针指向对象的不同而不同,即调用所指对象的函数。

父类的析构函数必须是虚的析构函数,否则容易造成内存泄漏,

重载、覆盖参见林锐的《c++高质量编程指南》

 

9、 菱形继承类

是A有两个子类B1和B2,C类继承自B1和B2。

存在问题:占用了更多的存储空间(每个子类内存中都拥有父类内存的一份拷贝),基类的构造(析构)函数被调用了两次,调用基类的成员函数时(不知道通过那个父类来调用基类的构造函数)会产生二义性。

 

解决办法:继承时在基类前面加一个virtual关键字,即虚拟继承。

原文链接: https://www.cnblogs.com/xyl-share-happy/archive/2012/09/15/2687011.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C++编程关键路径(二)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/62882

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 上午10:38
下一篇 2023年2月9日 上午10:39

相关推荐