1.3 C++的设计
tips: "If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would detroy civilization." -- Gerald Weinberg
--------------------------------
这一句是stroustrup关于类设计的一句忠告。我觉得是一个设计风格的问题,也挺重要的。
首先说说“定义”。在C++中有几个相互关联的术语:“声明”(declaration)、“定义”(definition)和“实现”(implement)。初次学习C/C++的时候,我总是把他们三个混为一谈,或者说没有想去认真区别一下彼此。看过好多书之后发现,这点其实蛮重要的。
也就是说,声明一般仅仅为两项内容:名字(变量),以及名字的类型(当然一般还需要一个逗号,或分号)。例如:
cpp 代码
int
intVar;
double yourCash, myCash;
class Student;
std:: string studentName;
int intMax( int , int );
double yourCash, myCash;
class Student;
std:: string studentName;
int intMax( int , int );
而向如下的样式则不能称之为“声明”,而是“声明”
+
“定义”:
cpp 代码
int
intVar
=
0
;
double yourCash = 0.0 , myCash = 10e + 10 ;
class myClass {}; // an empty class;
std:: string studentName(“”);
double yourCash = 0.0 , myCash = 10e + 10 ;
class myClass {}; // an empty class;
std:: string studentName(“”);
-
定义(或对内置类型也可叫初始化):一个语句(块),它为程序中的一个类型(或变量)规定了其内部框架(或值)。例如:
-
实现:主要针对类成员以及函数而言,即用具体算法实现成员、函数既定的功能。例如:
cpp 代码int
Student::number( void ) const {
return _studentNo;
}所以有的时候,函数的定义也可以成为实现。而有的时候,类的定义却可以成为类的声明。 [3]通过上面的例子,我们已经可以看出,一个内置的类型和一个用户自定义的类型( class 类)的定义的确不同。为了实现自定义类型所期望表达的类型内涵,我们必须给出需要的数据成员和用户接口 [4] 。但内置类型则不用,这是内置定义好了的。我们所要关心的是:为保持程序整体风格的一致,通过定义合适的用户接口,使用户在使用这些接口时,感觉就像使用一个内置类型一样。这将大大降低使用及维护成本。例如我们想有一个用于数学、工程计算的 Matrix 类。当我们设计的该类的时候,我们就应该提供与 STL 相一致的接口、即功能,如我们可以这样声明、使用一个 Matrix 类:cpp 代码using namespace gavin::math;
Matrix matrix1( 3 , 5 ), matrix( 5 , 3 );
matrix[ 0 ][ 0 ] = 3 , matrix1[ 0 ][ 1 ] = 2 ;
// …初始化matrix1和matrix2;
Matrix result( matrix1 * matrix2 );
cout << “We can print out the result: “ << result << endl;
cout << “after multiply with 3 is : “ << 3 * result << endl;
cout << “And we can plus them: “ << matrix1 + matrix2 << endl;
cout << “Sure can minus: “ << matrix1 – matrix2 << endl;
cout << “Even get a negative: “ << - matrix2 << endl;
cout << “Get the Matrix’s size: “ << matrix2.size() << endl;
Matrix::iterator iter = result.begin(),
iterEnd = result.end();
for (; iter != iterEnd; ++ iter) {
cout << * iter << endl;
}我们所编写、自定义的类型,在使用上不仅要有与标准 STL 相同的接口名称,而且更主要的是要提供与 STL 接口相同的语义 -- 相同的接口名称就应该实现相同或起码也是相近、不冲突的功能。而不应该采用 C 或其他语言的惯例,用一个函数去实现类似的功能。例如以下的用法是可以避免的:cpp 代码printMatrix(matrix1); printMatrix(matrix2);
matrixPlus(matrix1, matrix2);假如你有些实践经验,那么采取标准 STL 风格的自定义类型的好处是显而易见的。无论是使用,还是后期的维护。
-
int
intVar;
//
declaration;
intVar = 3 ; // definition;
// class definition;
class Student {
int _studentNo;
char _gender;
std:: string _birth;
public :
int number( void ) const ;
char gender( void ) const ;
std:: string birth( void ) const ;
};
// a function definition/implement;
int intMax( int a, int b) {
return (a > b ? a : b);
}
intVar = 3 ; // definition;
// class definition;
class Student {
int _studentNo;
char _gender;
std:: string _birth;
public :
int number( void ) const ;
char gender( void ) const ;
std:: string birth( void ) const ;
};
// a function definition/implement;
int intMax( int a, int b) {
return (a > b ? a : b);
}