济宁网站建设是什么,在线商城网站制作,湖北营销型网站建设费用,基于mvc4商务网站开发数据类型
基本的内置类型 修饰符类型
C 允许在 char、int 和 double 数据类型前放置修饰符。 修饰符是用于改变变量类型的行为的关键字#xff0c;它更能满足各种情境的需求。
类型限定符 函数
以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的 允许在 char、int 和 double 数据类型前放置修饰符。 修饰符是用于改变变量类型的行为的关键字它更能满足各种情境的需求。
类型限定符 函数
以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的但在逻辑上划分通常是根据每个函数执行一个特定的任务来进行的。 函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。 定义函数 C 中的函数定义的一般形式如下
return_type function_name( parameter list )
{body of the function
}在 C 中函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分 返回类型一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值在这种情况下return_type 是关键字 void。函数名称这是函数的实际名称。函数名和参数列表一起构成了函数签名。参数参数就像是占位符。当函数被调用时您向参数传递一个值这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的也就是说函数可能不包含参数。函数主体函数主体包含一组定义函数执行任务的语句。 函数声明 函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数声明包括以下几个部分
return_type function_name( parameter list );调用函数
Lambda 函数与表达式
Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用比如可以将它们赋给变量和作为参数传递还可以像函数一样对其求值。 Lambda 表达式本质上与函数声明非常类似。Lambda 表达式具体形式如下:
[capture](parameters)-return-type{body}在Lambda表达式内可以访问当前作用域的变量这是Lambda表达式的闭包Closure行为。 与JavaScript闭包不同C变量传递有传值和传引用的区别。可以通过前面的[]来指定
[] // 沒有定义任何变量。使用未定义变量会引发错误。
[x, y] // x以传值方式传入默认y以引用方式传入。
[] // 任何被使用到的外部变量都隐式地以引用方式加以引用。
[] // 任何被使用到的外部变量都隐式地以传值方式加以引用。
[, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用。
[, z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。另外有一点需要注意。对于[]或[]的形式lambda 表达式可以直接使用 this 指针。但是对于[]的形式如果要使用 this 指针必须显式传入
[this]() { this-someFunc(); }();数据结构
结构是 C 中另一种用户自定义的可用的数据类型它允许您存储不同类型的数据项。结构用于表示一条记录 定义结构 为了定义结构您必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型struct 语句的格式如下
//定义结构体
struct type_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;//示例
struct Books
{char title[50];char author[50];char subject[100];int book_id;
};void printBook( struct Books book )
{cout 书标题 : book.title endl;cout 书作者 : book.author endl;cout 书类目 : book.subject endl;cout 书 ID : book.book_id endl;
}
int main( )
{Books Book1; // 定义结构体类型 Books 的变量 Book1// Book1 详述strcpy( Book1.title, C 教程); //赋值//strcpy把含有\0结束符的字符串复制到另一个地址空间返回值的类型为char*strcpy( Book1.author, Runoob); strcpy( Book1.subject, 编程语言);Book1.book_id 12345; //赋值// 输出 Book1 信息printBook( Book1 );
}type_name 是结构体类型的名称member_type1 member_name1 是标准的变量定义比如 int i; 或者 float f; 或者其他有效的变量定义。在结构定义的末尾最后一个分号之前您可以指定一个或多个结构变量这是可选的。下面是声明一个结构体类型 Books变量为 book 访问结构成员 为了访问结构的成员我们使用成员访问运算符.。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。
指向结构的指针
您可以定义指向结构的指针方式与定义指向其他类型变量的指针相似如下所示
struct Books *struct_pointer;现在您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址请把 运算符放在结构名称的前面如下所示
struct_pointer Book1;为了使用指向该结构的指针访问结构的成员您必须使用 - 运算符如下所示
struct_pointer-title;存储类
存储类定义 C 程序中变量/函数的范围可见性和生命周期。这些说明符放置在它们所修饰的类型之前。
auto auto关键字用于两种情况声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。 register register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小通常是一个词且不能对它应用一元的 ‘’ 运算符因为它没有内存位置。 static static 存储类指示编译器在程序的生命周期内保持局部变量的存在而不需要在每次它进入和离开作用域时进行创建和销毁。因此使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。 static 修饰符也可以应用于全局变量。当 static 修饰全局变量时会使变量的作用域限制在声明它的文件内。 在 C 中当 static 用在类数据成员上时会导致仅有一个该成员的副本被类的所有对象共享。 extern extern 存储类用于提供一个全局变量的引用全局变量对所有的程序文件都是可见的。当您使用 ‘extern’ 时对于无法初始化的变量会把变量名指向一个之前定义过的存储位置。 当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解extern 是用来在另一个文件中声明一个全局变量或函数。 mutable mutable 说明符仅适用于类的对象这将在本教程的最后进行讲解。它允许对象的成员替代常量。也就是说mutable 成员可以通过 const 成员函数修改。 thread_local (C11) 使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建并在销毁线程时销毁。 每个线程都有其自己的变量副本。 thread_local 说明符可以与 static 或 extern 合并。 可以将 thread_local 仅应用于数据声明和定义thread_local 不能用于函数声明或定义。 类对象
定义一个类需要使用关键字 class然后指定类的名称并类的主体是包含在一对花括号中主体包含类的成员变量和成员函数 示例
class Box
{public:double length; // 盒子的长度double breadth; // 盒子的宽度double height; // 盒子的高度
};访问数据成员 类的对象的公共数据成员可以使用直接成员访问运算符 . 来访问。
类成员函数
函数定义 1、先进行函数声明再在类外进行函数实现使用范围解析运算符 :: 来定义 2、成员函数可以定义在类定义内部
类访问修饰符
类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的
类构造函数 析构函数
类的构造函数是类的一种特殊的成员函数它会在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同的并且不会返回任何类型也不会返回 void。构造函数可用于为某些成员变量设置初始值。 class Line
{public:void setLength( double len );double getLength( void );Line(); // 这是无参构造函数Line(double len); // 这是有参构造函数private:double length; //值由有参构造方法赋值
};
// 无参构造函数
Line::Line(void)
{cout Object is being created endl;
}// 有参构造函数
Line::Line( double len)
{cout Object is being created, length len endl;length len;
}//主程序进行对象的的实例化
int main( )
{Line line(); //无参构造实例化对象Line line(10.0); //有参构造实例化对象return 0;
}
使用初始化列表来初始化字段 假设有一个类 C具有多个字段 X、Y、Z 等需要进行初始化同理地您可以使用上面的语法只需要在不同的字段使用逗号进行分隔 C::C( double a, double b, double c): X(a), Y(b), Z(c){ ....} Line::Line( double len)
{length len;
}Line::Line( double len): length(len)
{
}类的析构函数是类的一种特殊的成员函数它会在每次删除所创建的对象时执行。 析构函数的名称与类的名称是完全相同的只是在前面加了个波浪号~作为前缀它不会返回任何值也不能带有任何参数。析构函数有助于在跳出程序比如关闭文件、释放内存等前释放资源。 class Line
{public:void setLength( double len );double getLength( void );Line(); // 这是构造函数声明~Line(); // 这是析构函数声明private:double length;
};
Line::~Line(void)
{cout Object is being deleted endl;
}友元函数 类的友元函数是定义在类外部但有权访问类的所有私有private成员和保护protected成员。尽管友元函数的原型有在类的定义中出现过但是友元函数并不是成员函数。 友元可以是一个函数该函数被称为友元函数友元也可以是一个类该类被称为友元类在这种情况下整个类及其所有成员都是友元。 如果要声明函数为一个类的友元需要在类定义中该函数原型前使用关键字 friend class Box
{
public:friend void printWidth( Box box );
};声明类 ClassTwo 的所有成员函数作为类 ClassOne 的友元需要在类 ClassOne 的定义中放置如下声明 friend class ClassTwo; #include iostreamusing namespace std;class Box
{double width;
public:friend void printWidth( Box box );void setWidth( double wid );
};// 成员函数定义
void Box::setWidth( double wid )
{width wid;
}// 请注意printWidth() 不是任何类的成员函数
void printWidth( Box box )
{/* 因为 printWidth() 是 Box 的友元它可以直接访问该类的任何成员 */cout Width of box : box.width endl;
}// 程序的主函数
int main( )
{Box box;// 使用成员函数设置宽度box.setWidth(10.0);// 使用友元函数输出宽度printWidth( box );return 0;
}当上面的代码被编译和执行时它会产生下列结果 Width of box : 10 指向类的指针
指针解释指针就是一个存储地址的变量
每一个变量或实例化的对象都有一个地址。使用()运算符访问其地址
定义指针使用*运算符
//定义指针
type *varnameint var 20
int *IP var
输出IP是var的地址 ox0021111
输出*IP是var的值 20类的指针与指向结构的指针类似访问指向类的指针的成员需要使用成员访问运算符 -就像访问指向结构的指针一样。与所有的指针一样您必须在使用指针之前对指针进行初始化。
声明和初始化指向类的指针
#include iostreamclass MyClass {
public:int data;void display() {std::cout Data: data std::endl;}
};
int main() {// 创建类对象MyClass obj;obj.data 42;// 声明和初始化指向类的指针MyClass *ptr obj;// 通过指针访问成员变量std::cout Data via pointer: ptr-data std::endl;// 通过指针调用成员函数ptr-display();return 0;
}动态分配内存
int main() {// 动态分配内存创建类对象MyClass *ptr new MyClass;ptr-data 42;// 通过指针调用成员函数ptr-display();// 释放动态分配的内存delete ptr;return 0;
}指向类的指针作为函数参数
指向类的指针可以作为函数参数传递
// 函数接受指向类的指针作为参数
void processObject(MyClass *ptr) {ptr-display();
}
int main() {MyClass obj;obj.data 42;// 将指向类的指针传递给函数processObject(obj);return 0;
}this 指针
this 指针是一个特殊的指针它指向当前对象的实例。 在 C 中每一个对象都能通过 this 指针来访问自己的地址。 this是一个隐藏的指针可以在类的成员函数中使用它可以用来指向调用对象。 当一个对象的成员函数被调用时编译器会隐式地传递该对象的地址作为 this 指针。 友元函数没有 this 指针因为友元不是类的成员只有成员函数才有 this 指针。 实例
class Box
{public:// 构造函数定义Box(double l2.0, double b2.0, double h2.0){cout 调用构造函数。 endl;length l;breadth b;height h;}double Volume(){return length * breadth * height;}int compare(Box box){return this-Volume() box.Volume();}private:double length; // 宽度double breadth; // 长度double height; // 高度
};int main(void)
{Box Box1(3.3, 1.2, 1.5); // 声明 box1Box Box2(8.5, 6.0, 2.0); // 声明 box2if(Box1.compare(Box2)) //Box1调用compare方法传入Box2对象{cout Box2 的体积比 Box1 小 endl;}else{cout Box2 的体积大于或等于 Box1 endl;}return 0;
}以上代码执行输出结果为 调用构造函数。 调用构造函数。 Box2 的体积大于或等于 Box1 继承
面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类这使得创建和维护一个应用程序变得更容易。这样做也达到了重用代码功能和提高执行效率的效果。
当创建一个类时您不需要重新编写新的数据成员和成员函数只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类新建的类称为派生类。 基类 派生类 一个类可以派生自多个类这意味着它可以从多个基类继承数据和函数。定义一个派生类我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名形式如下
class derived-class: access-specifier base-class其中访问修饰符 access-specifier 是 public、protected 或 private 其中的一个base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier则默认为 private。
多继承
继承类型 当一个类派生自基类该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。
我们几乎不使用 protected 或 private 继承通常使用 public 继承。当使用不同类型的继承时遵循以下几个规则
公有继承public当一个类派生自公有基类时基类的公有成员也是派生类的公有成员基类的保护成员也是派生类的保护成员基类的私有成员不能直接被派生类访问但是可以通过调用基类的公有和保护成员来访问。保护继承protected 当一个类派生自保护基类时基类的公有和保护成员将成为派生类的保护成员。私有继承private当一个类派生自私有基类时基类的公有和保护成员将成为派生类的私有成员。
多继承即一个子类可以有多个父类它继承了多个父类的特性。
class 派生类名:继承方式1基类名1,继承方式2基类名2,…
{
派生类类体
};重载运算符和重载函数
允许在同一作用域中的某个函数和运算符指定多个定义分别称为函数重载和运算符重载。
重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明但是它们的参数列表和定义实现不相同。
当您调用一个重载函数或重载运算符时编译器通过把您所使用的参数类型与定义中的参数类型进行比较决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程称为重载决策。
重载的运算符是带有特殊名称的函数函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样重载运算符有一个返回类型和一个参数列表。
//一个返回类型 关键字operator 重载的运算符 一个参数列表
Box operator(const Box, const Box);示例
class Box
{public:double getVolume(void){return length * breadth * height;}void setLength( double len ){length len;}void setBreadth( double bre ){breadth bre;}void setHeight( double hei ){height hei;}// 重载 运算符用于把两个 Box 对象相加Box operator(const Box b){Box box;box.length this-length b.length;box.breadth this-breadth b.breadth;box.height this-height b.height;return box;}private:double length; // 长度double breadth; // 宽度double height; // 高度
};// 程序的主函数
int main( )
{Box Box1; // 声明 Box1类型为 BoxBox Box2; // 声明 Box2类型为 BoxBox Box3; // 声明 Box3类型为 Boxdouble volume 0.0; // 把体积存储在该变量中// Box1 详述Box1.setLength(6.0); Box1.setBreadth(7.0); Box1.setHeight(5.0);// Box2 详述Box2.setLength(12.0); Box2.setBreadth(13.0); Box2.setHeight(10.0);// Box1 的体积volume Box1.getVolume();cout Volume of Box1 : volume endl;// Box2 的体积volume Box2.getVolume();cout Volume of Box2 : volume endl;// 把两个对象相加得到 Box3Box3 Box1 Box2;// Box3 的体积volume Box3.getVolume();cout Volume of Box3 : volume endl;return 0;
}下面是可重载的运算符列表 下面是不可重载的运算符列表 多态
多态按字面的意思就是多种形态。当类之间存在层次结构并且类之间是通过继承关联时就会用到多态。 C 多态意味着调用成员函数时会根据调用函数的对象的类型来执行不同的函数。 实际是有不同的子类继承父类的方法然后子类进行了重写其子类的实现逻辑都不一样 #include iostream
using namespace std;class Shape {protected:int width, height;public:Shape( int a0, int b0){width a;height b;}int area(){cout Parent class area : endl;return 0;}
};
class Rectangle: public Shape{public:Rectangle( int a0, int b0):Shape(a, b) { }int area (){ cout Rectangle class area : endl;return (width * height); }
};
class Triangle: public Shape{public:Triangle( int a0, int b0):Shape(a, b) { }int area (){ cout Triangle class area : endl;return (width * height / 2); }
};
// 程序的主函数
int main( )
{Shape *shape;Rectangle rec(10,7);Triangle tri(10,5);// 存储矩形的地址shape rec;// 调用矩形的求面积函数 areashape-area();// 存储三角形的地址shape tri;// 调用三角形的求面积函数 areashape-area();return 0;
}Parent class area : Parent class area : 函数 area() 被编译器设置为基类中的版本这就是所谓的静态多态或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定因为 area() 函数在程序编译期间就已经设置好了。 但现在让我们对程序稍作修改在 Shape 类中area() 的声明前放置关键字 virtual 虚函数 虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时会告诉编译器不要静态链接到该函数。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数这种操作被称为动态链接或后期绑定。
纯虚函数 您可能想要在基类中定义虚函数以便在派生类中重新定义该函数更好地适用于对象但是您在基类中又不能对虚函数给出有意义的实现这个时候就会用到纯虚函数。
class Shape {protected:int width, height;public:Shape( int a0, int b0){width a;height b;}// pure virtual functionvirtual int area() 0;
};0 告诉编译器函数没有主体上面的虚函数是纯虚函数。
数据封装
封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念这样能避免受到外界的干扰和误用从而确保了安全。数据封装引申出了另一个重要的 OOP 概念即数据隐藏。
数据封装是一种把数据和操作数据的函数捆绑在一起的机制数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
C 通过创建类来支持封装和数据隐藏public、protected、private。我们已经知道类包含私有成员private、保护成员protected和公有成员public成员。默认情况下在类中定义的所有项目都是私有的。 意思是属性都是private访问修饰符然后用函数来进行访问和修改 class Adder{public:// 构造函数Adder(int i 0){total i;}// 对外的接口void addNum(int number){total number;}// 对外的接口int getTotal(){return total;};private:// 对外隐藏的数据int total;
};接口抽象类
接口描述了类的行为和功能而不需要完成类的特定实现。
C 接口是使用抽象类来实现的抽象类与数据抽象互不混淆数据抽象是一个把实现细节与相关的数据分离开的概念。
如果类中至少有一个函数被声明为纯虚函数则这个类就是抽象类。纯虚函数是通过在声明中使用 “ 0” 来指定的
设计抽象类通常称为 ABC的目的是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象它只能作为接口使用。如果试图实例化一个抽象类的对象会导致编译错误。
因此如果一个 ABC 的子类需要被实例化则必须实现每个纯虚函数这也意味着 C 支持使用 ABC 声明接口。如果没有在派生类中重写纯虚函数就尝试实例化该类的对象会导致编译错误。
可用于实例化对象的类被称为具体类。
#include iostream
using namespace std;
// 基类
class Shape
{
public:// 提供接口框架的纯虚函数virtual int getArea() 0;void setWidth(int w){width w;}void setHeight(int h){height h;}
protected:int width;int height;
};
// 派生类
class Rectangle: public Shape
{
public:int getArea(){ return (width * height); }
};
class Triangle: public Shape
{
public:int getArea(){ return (width * height)/2; }
};
int main(void)
{Rectangle Rect;Triangle Tri; Rect.setWidth(5);Rect.setHeight(7);// 输出对象的面积cout Total Rectangle area: Rect.getArea() endl;Tri.setWidth(5);Tri.setHeight(7);// 输出对象的面积cout Total Triangle area: Tri.getArea() endl; return 0;
}从上面的实例中我们可以看到一个抽象类是如何定义一个接口 getArea()两个派生类是如何通过不同的计算面积的算法来实现这个相同的函数。 设计策略
面向对象的系统可能会使用一个抽象基类为所有的外部应用程序提供一个适当的、通用的、标准化的接口。然后派生类通过继承抽象基类就把所有类似的操作都继承下来。
外部应用程序提供的功能即公有函数在抽象基类中是以纯虚函数的形式存在的。这些纯虚函数在相应的派生类中被实现。
这个架构也使得新的应用程序可以很容易地被添加到系统中即使是在系统被定义之后依然可以如此。