建设工程信息服务平台新网站,浦元品牌网站建设,江阴房产网510房产网,响应网站和模板网站有哪些C语言提供了一些内置的类型#xff0c;如char、int和double。对于一个类型#xff0c;如果编译器无须借助程序员在源码中提供的任何声明#xff0c;就知道如何表示这种类型的对象以及可以对它进行什么样的运算#xff0c;我们就称这种类型是内置的。非内置的类型称为用户自… C语言提供了一些内置的类型如char、int和double。对于一个类型如果编译器无须借助程序员在源码中提供的任何声明就知道如何表示这种类型的对象以及可以对它进行什么样的运算我们就称这种类型是内置的。 非内置的类型称为用户自定义类型(user-defined type , UDT)。用户自定义的类型包括每个ISO标准C实现都提供给程序员的标准库类型如stringvector和ostream。 我们为什么要创建自定义类型呢原因在于编译器不知道我们想在程序中使用的所有类型。它也不可能知道因为有用的类型实在太多了没有语言设计者或者编译器开发者能预知所有类型。通过类型我们可以在代码中直接、有效地表达我们的思想。类 C提供了两类用户自定义数据类型类和枚举。类是到目前为止最常用也是最重要的概念描述机制因此我们首先把注意力放在类上。类能够在程序中直接地表达概念。一个类是一个(用户自定义)类型是它指出这种类型的对象如何表示如何创建如何使用以及如何销毁。在C中(以及大多数现代程序设计语言中)类是构造大型程序的关键的基本组成部分对小程序也同样的非常有用。 一个类就是一个用户自定义类型由一些内置类型和其他用户自定义类型的对象以及一些函数组成。这些用来定义类的组成部分称为成员(member)。一个类可以有0个或多个成员例如:class X
{
public:int m; //data memberint mf(int v) {int old m; m v; return old;} //成员函数
} 成员可以有许多种类别大多数要么是数据成员定义了类对象的表示方法要么是函数成员提供类对象之上的运算。类成员的访问使用这种符号对象.成员。 我们通常把一个类看做一个接口加上一个实现。接口是类声明的一部分用户可以直接访问它。实现是类声明的另一部分用户只能通过接口间接访问它。公共的接口用标号public:标识实现用private:标识。你可以将一个类声明理解为如下形式:class X
{public:private:
}类成员默认是私有的也就是说如下代码所示class X
{int mf(int);//...
};等价于class X
{private:int mf(int);// ...
};因此下面的代码是错误的X x;
int y x.mf();用户不能直接访问一个私有成员应通过一个公有函数来访问例如class X
{int m;int mf(int);public:int f(int i) { m i; return mf(i);}
};
X x;
int y x.f(2);我们用私有和公用之间的差别来描述接口(类的用户视图)和实现细节(类的实现者视图)之间的重要区别。C提供了一种很有用的简化的功能可用来描述没有私有实现细节的类。这种语法功能就是结构一个结构就是一个成员默认为公用属性的类struct X
{int m;// ...
};意味着class X
{public:int m;// ...
};结构主要用于成员可以取任意值的数据结构即我们不能定义结构有意义的不变式。与类同名的成员函数是特殊的成员函数称为构造函数(constructor)专门用于类对象的初始化(构造)。如果一个类具有需要参数的构造函数而程序员忘记利用它初始化类对象则编译器会捕获这个错误。C提供了一种专用的而且很方便的语法来进行这种初始化例如struct Date {int y,m,d; Date(int y, int m, int d); void add_day(int n);};
Date my_birthday; //错误没有初始化成员。
Date today(12,24,2007); //错误运行时错误。
Date last(2000,12,31); //正确。运算符重载你可以在类或枚举对象上定义几乎没有C运算符这通常称为运算符重载(operator overloading)。这种机制用于为用户自定义类型提供习惯的符号表示方法。enum Month {Jan 1,Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
Month operator(Month m)
{m (m Dec)?Jan:Month(m1);return m;
}其中?:是“算术if运算符:当(m Dec)时m的值变为Jan,否则m的值为Month(m1)。这是十二月后绕回一月这一事实的一种非常简洁的描述方法。我们可以像如下代码一样使用Month类型。Month m Sep;
m; //m变为Oct
m; //m变为Nov
m; //m变为Dec
m; //m变为Jan你可能觉得增加Month对象值这样的操作没那么常用不至于设计一个专门的运算符。可能确实是这样那么输出运算符又如何呢如下代码定义了一个输出运算符:vectorstring month_tbl;ostream operator(ostream os, Month m) { return os month_tbl[m];} 你可以为自己的类型重新定义几乎没有的C运算符,如、-、*、/、%、[]、()、^、、、、、和等。但你不能定义新的运算符。 一个重载的运算符必须作用于至少一个用户自定义类型的运算对象:int operator(int ,int); //错误不能重载内置运算符
vector operator(const vector, const vector ); //OK
vector operator(const vector, int); //OK 一个一般性的原则是除非你真正确定重载运算符能大大改善代码否则不要为你的类型定义运算符。而且重载运算符应该保持其原有意义就应该是加法二元运算符*就应该表示乘法[]表示元素访问()表示调用等等。这只是建议并不是C语言规则但这是一个有益的建议:按习惯使用运算符例如只用做加法对我们理解程序会有极大的帮助。毕竟这种习惯用法源于人们千百年使用数学符号的经验。相反含混不清的运算符和常规不符的使用方式是混乱和错误之源。类接口 类的公有接口和实现部分应该分离。但是如何来设计一个好的接口呢 (1)保持接口的完整性。 (2)保持接口的最小化。 (3)提供构造函数。 (4)支持(或禁止) 拷贝。 (5)使用类型来提供完善的类型检查。 (6)支持不可修改的成员函数。 (7)在析构函数中释放所有的资源。 前两条原则可以归结为保持接口尽可能小但不要更小了“。我们希望接口尽量小是因为小的接口易于学习和记而实现者也不会为不必要的和很少使用的功能浪费大量时间。小的接口还意味着当错误发生时我们中需要检查很少的函数来定位错误。平均来看公有成员函数越多查找bug就越困难调试带公有数据的类是非常复杂的不要让陷入其中。当然前提还是要保持完整性否则接口就没有用处了。如果一个接口无法完成我们真正需要做的全部工作我们是不会使用它的。 转载于:https://blog.51cto.com/hthinker/1588473