自己的成员函数,只能声明。 多重继承会带来一些麻烦,比方说父类们都继承了同一个类,那么此派生类会继承那个类两次,此时就要用虚基类来解决问题,另外,多重继承也会出现一些重名的问题。把“接口”从类中分离出来是有好处的,它清楚地说明了类中一定会存在的方法,如果用一个纯抽象类来代替接口,则可能会出现“Is a”这样的混淆,即――Dog是Animal,并且同时是CanEat, CanRun这样的混淆,而正确的看法应该是:Dog是animal,且存在CanEat、CanRun这样的能力。 因此到现在,我都有个习惯,一个类最多继承一个包含了成员或实现多个成员函数的类,并且可以继承多个纯抽象类(不包含成员字段,且仅包含成员函数的声明的类)。当然,这种习惯可能在某些情况下是有局限性的。
4、typedef和#define 先说说define吧。宏定义是提高程序效率的一种有效手段,因为它的时间消耗在了编译器。我们可以把很多常用的函数写成宏定义,这样运行它的时候参数就不会反复出栈入栈影响效率了,C++中也可以把函数定义成inline来提高效率。define在一定程度上可以提高代码的可读性,但是漫天的define会让人疑惑。因此,在C#中define的功能被做了限制,即define不能定义一个宏为一个值,它仅仅只能定义,以及判断它是否定义了,最常见的用途就是#define DEBUG,来进行某些调试。 typedef,以及C++11中常用的using,是给类型命别名的。它主要的作用,在我看来有两个:一是提高代码的可读性,例如,一个string类型的可读性肯定比const char*高,一个strVectorWithVector的可读性肯定比vector
>高,同define一样,漫天的typedef同样会降低代码的可读性。第二个作用是增加软件的可移植性。在机器A上,int占8个自己,B机器上,int占16个字节,那么在A机器上定义的int a可能在B机器上都要改成long a,这样的工作量巨大而且容易出错。因此,在A机器上,用typedef将int命名为MyInt,在B机器上,将MyInt对应的类型改成long就实现了所有类型的改变。 不过,这样的类型移植在C#和Java上应该出现得很少的,因为它们都有各自的“
虚拟机”――.NET库有CLR,
Java有Java虚拟机,它们在不同的终端上会处理这样的兼容性问题的。
5、内存管理 内存管理是C++程序员的噩梦,虽然标准库引入了boost中的shared_ptr,但是它仍然没有一个垃圾回收机制,shared_ptr使用起来也有一定难度,不像“垃圾回收”那样可以无脑使用,C++的设计者可能认为程序的所有控制权应该交给程序员,但是不是所有的程序员(或他们的老板)都是那么有耐心,一个完善的内存管理机制可能需要花费相当大的时间。ObjectiveC引入了autorelease垃圾回收机制,但我认为C++在下一次标准出来之前也不会有垃圾回收机制。 在C#和Java中,一个类的回收是不定时的,但是你可以定义它们在回收时应该要做些什么,而在C++中,析构神马的,都要自己写。
以上列举了几点C++十分灵活的地方,它灵活的地方还有许多,如迭代器――C++中,如果要使用range for,则这个类必须拥有begin(),end(),它们返回一个迭代器,这个迭代器可以是自己定义的一个类,它必须实现解引用*运算符、!=运算符和++运算符。标准库中提供了各种各样复杂的迭代器,而在range for出来之前,QT中已经实现了foreach“语句”。在C#、Java中,如果要使用foreach,类必须要实现迭代器接口。 C++没有“程序集”的概念,所以也就不存在反射机制,能够使用decltype已经算是一种“突破”了。C++中,一个对象即一块内存,在C#、Java中,我们可以用GetType或.class方法来获取类型的信息。
不得不说,C++中有很多“人为规定”,大部分操作、内存管理需要自己实现,对计算机的结构需要有很清晰地了解才能写出好的程序。C++如此复杂,征服它会不会很有成就感!
|