但却是唯一可行的方案"/>
C专家编程 第11章 你懂得C,所以C++不再话下 11.19 它或许过于复杂,但却是唯一可行的方案
它或许过于复杂,但却是唯一可行的方案
C语言原先的设计哲学“所有的特性都不需要隐式的运行时支持”已经做了一定的妥协。
C++对C语言的改进
*在C语言中,初始化一个字符数组的方式很容易产生这样一个错误,即数组很可能没有足够的空间存放结尾的NUL字符。C++对此作了一些改进,像char b[3] = "Bob"这样的表达式被认为是一个错误,但它在C语言中却是合法的。
*类型转换既可以写成像float(i)这样看上去更顺眼的形式,也可以写成像(float)i这样稍显怪异的C语言风格的形式。
*C++允许一个常量整型来定义数组的大小:
const int size = 128;
char a[size];
这在C++中是允许的,但在C语言中却是错误的。
*声明可以穿插于语句之间。在C语言中,一个语句块中所有声明都必须放在所有语句的前面。C++去掉了这个专横的限制,做得非常好。既然这种做法也会引起与C语言的不兼容,那为什么不进行的彻底一些,为C语言声明语法提供一种更简单的替代方案呢?
从C转换到C++
学习C++最好的方式就是从它的ANSI C子集开始编程。把C语言作为一种可移植的机器语言事实上会使链接和调试复杂化。名字混合并不可靠,它会带来可怕的危险,并长期存在于C++中。名字混合是一种在不同的文件间进行类型检查的权宜之策,但它暗示你所有的C++代码必须用同一个编译器编译,因为名字混合策略在不同的编译器上可能各不相同。对于C++的复用类型而言,这是一个巨大的缺陷,因为它有效地防止了二进制一级的复用。
这里有一个代表性的例子,说明了C语言并非C++的子集,并提示何处可能隐藏着麻烦。
在C++中存在,但在C语言中却不存在的限制有:
*在C++中,用户代码不能调用main()函数,但在C语言中却是允许的(不过这种情况极为罕见);
*完整的函数原型声明在C++中是必须的,但在C语言中却没这么严格;
*在C++中,有typedef定义的名字不能与已有的结构标签冲突,但在C语言中却是允许的(它们分属不同的名字空间);
/*
** distinction of typedef in c and c++.
*/
/*
** typdef_struct_label.cpp.
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct struct_a{
int a;
} struct_a;
int main( void ){
return EXIT_SUCCESS;
}
输出:
/*
** typdef_struct_label.c.
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct struct_a{
int a;
} struct_a;
int main( void ){
return EXIT_SUCCESS;
}
输出:
*当void*指针赋值给另一个类型的指针时,C++规定必须进行强制类型转换,但在C语言中却无必要。
在C++和C语言中具有不同含义的特性有下面这些。
*C++至少增加了十几个关键字。这些关键字在C语言中可以作为标识符使用,但如果这样做了,用C++编译器编译这些代码时就会产生错误信息。
*在C++中,声明可以出现在语句可以出现的任何地方。在C语言中的代码块中,所有的声明必须出现在所有语句的前面。
*在C++中,一个内层作用域的结构名将会隐藏外层空间中相同的文件名。在C语言中,则非如此。
*在C++中,字符常量的类型是char,但在C语言中,它们的类型是int。也就是说,在C++中,sizeof('a')的结果是1,而在C语言中,它的值要大些。
*由于C++增加了新的//注释符,因此有时会在两种语言中产生微妙而怪异的差别。
protected abstract virtual base pure virtual private destructor是什么
上面这句话可以分为两个部分:从一个protected abstract virtual base派生而来的pure virtual private destructor
*private destructor就是一个对象离开其生存范围时所调用的函数。private表示它只能被本类的成员函数或友元(friend)访问。
*pure virtual函数本身没有代码,但他可以通过继承作为派生类虚拟函数实现的指导准则。
*pure virtual destructor只有在被派生类覆盖以后才有意义。由于析构函数能够自动进行类缺省的清理工作,如同调用成员或基类的析构函数一样,所以通常并不需要在析构函数的定义中显式地编写任何代码。
让我们看一下第二部分
*abstract virtual base表示基类是被多个多重继承的类所共享(它是虚基类),它至少包含一个纯虚函数(pure virtual function),其他的类通过继承从它派生(所谓抽象基类)。虚基类也有特殊的初始化语义。
*protected abstract virtual base类是指我们我们的类是以protected形式派生的。该类的后续派生类可以访问父类的信息,但其他的类则不允许。
现在,把它们放在一起,一个protected abstract virtual base pure virtual private destructor就是一个析构函数,它具有下列特点:
*只能被该类的成员函数或友元调用
*在声明它的基类中没有定义,但它将在派生类中定义;
*它(指派生类)共享一个多重继承的基类;
*它(指基类)以protected方式继承。
在C++的代码中,大概可以这样表述:
class vbc {
protected: virtual void v() = 0;
private: virtual ~vbc() = 0;
};
//vbc是一个抽象类,因为它包含纯虚拟函数
class X : virtual protected vbc {
//X虚拟地从继承于vbc,而且vbc的protected成员也是X的protected成员
//所以vbc是X的protected abstract virtual base类
protected: void v() {
}
~X() {
/*执行一些X类的清理工作*/
}
};
//当一个X对象被销毁时,X::~X被调用,然后...
/*X的protected abstract virtual base pure virtual private destructor也被调用,所以尽管它是纯函数,但它仍然需要定义。*/
/*
** inheritance and polymorphism
*/
#include<stdio.h>
#include<stdlib.h>
class vbc {
protected: virtual void v() = 0;
/*
** [Error] 'vbc::~vbc()' is private
*/
private: virtual ~vbc() = 0;
};
//vbc是一个抽象类,因为它包含纯虚拟函数
class X : virtual protected vbc {
//X虚拟地从继承于vbc,而且vbc的protected成员也是X的protected成员
//所以vbc是X的protected abstract virtual base类
protected: void v() {
printf( "v function is called in class X!\n" );
}
~X() /* [Error] within this context */{
/*执行一些X类的清理工作*/
}
};
int main( void ){
return EXIT_SUCCESS;
}
输出:/* 你可以试着修改这个程序。例如变动x的析构函数的访问权限。 */
更多推荐
C专家编程 第11章 你懂得C,所以C++不再话下 11.19 它或许过于复杂,但却是唯一可行的方案
发布评论