WEB开发网
开发学院软件开发C++ 学用C++的体会 阅读

学用C++的体会

 2008-03-08 12:25:43 来源:WEB开发网   
核心提示: 我在大学的时候,花了一个月时间学了C语言,学用C++的体会,后来,基本上做什么,在现实生活中也是有的,那么,都不用翻书了后来看C++,觉得挺简单
    
   我在大学的时候,花了一个月时间学了C语言,后来,基本上做什么,都不用翻书了
后来看C++,觉得挺简单,学了一周,想不就是在C语言的基础上,加了一个class吗,工作了一年看的书多了,用的多了,才真正发现自己是井底之蛙。以前,看了所有的VC的书,其实,现在发现VC!=C++,vc只是一个编程环境啊。C++是一门语言。C++的精髓之区在面向对象的思想,为什么可以定义一个类,如何继续一个。说到底是面向对象分析,面向对象设计,也就是OOA/OOD,C++的复杂在于它的范围很广,因为,我们工作往往只能用到它的一部分啊。比如我们很少用模板,很少用那些高级的应用,其实,说到底,是我们的水平不够,大家看看loki库也许就知道,template有多大的威力。我个人认为,template,跟虚函数一样,属于多态的,不过,虚函数是通过指针,实现,在运行时候,进行解析,而template是编译期解析,我想它的实现跟宏定义差不多,但是,更加高级。

   还有一个问题,C++的编译器其实为我们的代码做了很多的事情。假如,我们不知道的话,那么,就会经常出现错误,我们应该始终记住这么一句话:"通用的往往是不好的,不适合工程的"。比如说:
函数为什么能够重载?

   其实 ,C++,是这样实现函数的名称对应的

比如:
class A
{
  show(int a,int b);
  show(float a); 

};

   其实,它在内部是这样对应的:伪代码:

 show_INT_INT(int a,int b, void *this);
 show_FLOAT(float a,void *this);

   大家想想为什么会有一个this指针

   这样,自然,show()重载多少个都没有问题,从这也可以看出,内部实现,只是把函数的参数类型编进了函数名来实现重载,而没有把返回值编入,因此,函数名一样,参数个数一样,类型对应一样的,返回值不同的两个函数不能构成重载,会出现编译错误。(我们可以想想为什么不把返回值编入函数名里,假如,只有两个函数返回值不同,比如如下:

class B
{
 public:
  int PRint(int a);
  void print(int a);
}

   假如,把返回值也编入函数名的话,那么它们应该可以构成重载。当你这样如下调用时候,

 B a;
 a.print(20);

   编译器怎么知道它是调用那个函数。

2,函数参数传入传出的规则

   在函数调用的时候,有三种情况,第一种参数为数值,第二种为传指针,第三种传引用,此外,还有,为const,和non-const的区别。什么情况下该传数值,什么情况下不该传呢,我觉得假如参数是基本类型的话,没有关系,假如参数是对象的话,就不能传数值,因为,它会调用对应的构造函数。(知道为什么吗)

   解释:函数参数的传入,在函数的内部会产生几个临时变量,来拷贝函数的参数数值。比如:
 
fun(X a)
{
}

   那么,在函数对应的堆上,会为a变量开辟空间(m_a),并调用X类的拷贝构造函数来初始化化m_a,如下:X,m_a(a);类似这样。有时候,一个类包含很多变量,构造函数比较复杂,那么,这样的调用fun()会浪费很多系统时间。因此,极力反对用传值调用对象参数的函数。还有一个,大家经常碰到的问题,就似const 修饰参数与没有const的区别。有了const的修饰,在函数内部就不会为参数产生临时变量了,这样,自然,不会调用什么参数类的构造函数了,也不会为参数分配空间了。同时,这样的参数也不能在函数中改变它的数值。


3,拷贝构造函数
   我们往往忘了写这样一个函数,也许不需要。其实,我们没有写的时候,不过,编译器自动为我们生成一个。

比如:
class A{
  private: 
      int x;
     char *str_name;
 public :
    A(int x,char *str);   
};

   在这里,我们没有定义一个拷贝构造函数,假如出现这样的例子
fun(A x)
{
}

   从上边的例子,我们知道,调用fun()函数的时候,会要调用A类的拷贝构造函数的 这样,假如,没有定义的话,那么,系统产生一个拷贝构造函数(按照位拷贝变量的值),这样,我们知道,str_name只是一个指针,当临时变量的str_name成员也指向参数的str_name的位置时候,这样,我们就踏上了,一个地雷阵了。为什么,我们想啊,当执行完,fun()函数的时候,临时变量,在某个不确定的时刻就要free()掉,这样,临时变量str_name也会delete,而我们知道,这个str_name跟参数的str_name指向的同一个内存块,那么,当free一次后,那么它的内容就没有了这样,破坏了参数数据内容。


Kusk (2003-8-14 22:46:40) 读完此文,觉得有商榷之处: 

----------------------------------------------------- 我觉得假如参数是基本类型的话,没有关系,假如参数是对象的话,就不能传数值,因为,它会调用对应的构造函数。 

----------------------------------------------------- 对象也可以传值的,为什么调用构造函数就不能传值呢?只不过有时从效率的角度以及对某些不便复制的对象我们更倾向于使用引用罢了。 

----------------------------------------------------- 有了const的修饰,在函数内部就不会为参数产生临时变量了,这样,自然,不会调用什么参数类的构造函数了,也不会为参数分配空间了。 

----------------------------------------------------- 不知道仁兄从哪里得出的这个结论,假如这样的话我们似乎没有必要写fun(const yourClass& a)这样的以引用为参数函数声明,只须要写fun(const yourClass a)行了,但两者的确是有区别的,后者同样会调用拷贝构造函数产生临时变量! 

----------------------------------------------------- 拷贝构造函数我们往往忘了写这样一个函数,也许不需要。其实,我们没有写的时候,不过,编译器自动为我们生成一个。 

----------------------------------------------------- 我引用一下Lippman的《Inside the C++ Object Model 中文版》: “假如一个class未定义出copy constrUCtor,编译器就自动为它产生出一个”这句话不对,而是应该像ARM所说: Default constructors和copy constructors在必要的时候才由编译器产生出来。这个句子中的“必要”意指当class不展现bitwise copy semantics时,C++ Standard仍然保留了ARM的意义…… 按贴主的意思,可能他把“位拷贝(bitwise copy semantics)”也当成构造函数的职责了,事实上并非如此:位拷贝恰恰是没有定义构造函数(包括人为显式定义以及“必要时”系统的隐式定义)时才发生的。位拷贝的过程是编译器的动作,不属于构造函数调用。 
 


C++基础知识
以下来自www.csdn.net 作者taozhangzhi9

   C++的知识很多,有四库全书《C++ 程序设计》,《C Primer》,这本文章只想谈谈我个人所看到的用到的知识。加上自己的理解。很多东西可能没有系统化,而且,知识也是想到那写到那。

首先谈谈 类的对象的大小,

 class A
{
};

main()

   A a;
   cout< }

它的结果会是多少呢?

答案为1。

为什么?它没有定义任何变量,按道理,应该为0的啊。这是为了保证每一个对象的内存地址都是唯一的。比如:

   A a,b;

假如,长度为0,那么,a,b的内存地址,就可能是一个,这样,会产生一些不必要的麻烦。

那么
class A
{
   char m;
};

main()
{
   A a;
   cout< }

会打印结果为多少啊。答案为4

   这个问题叫Alignment,有一次,我就碰到这样郁闷的问题,我们的工程中代码都是用数组传送数据,比如坐标 x,y,那么就这样赋值

*(int *)&w[0]=x; 

*(int *)&w[4]=y;

   (或许大家很少用),这样的代码有一个缺点,送数据,取数据十分不方便,而且,由于有下标,因此,代码不好利用循环结构(还有不是四位的数据) 。只能一位一位的赋值,还有一个问题,就是,当工程一个约定变了的时候,所有的代码都要改动。不好reuse。

   因此,我希望借助结构strcut,或者class来改造程序代码,但是就碰到数据对齐问题。

   比如,我定义一个结构
struct A
{
   char type;
   int y;
};

   然后,这样使用。

char buf[MAX]; 
A a;
memcpy(buf,&a,sizeof(a));

   但是,却发现buf[]的内容有三个不是我需要的内容。其实,内容图示如下:

 
   我看了一些资料,说这是为了字节对齐,CPU存取数据是按照四位存取,这样,就不会取四位数据,一位是char type,三位是y的数据。作为编程者对这个有可能就不熟悉。还有类似的问题,以后,再叙。

类的数据的访问权限

   数据有三种权限:public,private,protected。C++是面向对象的语言,因此,它的许多概念来源于现实生活。比如这个权限问题就可以这么解释。基本类相当于父亲,子类相当于孩子,还有一个友元类,相当于朋友。

   比如,对于父亲有的东西(成员变量)是对任何人都共享的,大家都可以知道的,不是什么秘密。那么,用public来描述这样的东西。

   假如,有的东西,是只有不是外人不能知道的,也就是,儿子,好朋友都可以分享的秘密的话,那么,这样的东西用protected描述。

   同样,还有的东西,大人不想让小孩知道,但是,却对好朋友不保留,这样的事情,在现实生活中也是有的,那么,这样的用private描述。

Tags:学用 体会

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接