C++Notes03_数据类型(Data Type)
2017-02-23 10:26
369 查看
C++Notes03_数据类型(Data Type)
CNotes03_数据类型Data Type一struct
二namespace
三string
四vetor
五void
六类型转换
七运行时内存布局Runtime memory layout
八指针与引用Reference
九全局数据Global Data
十静态数据Static Data
C++数据类型新增或升级
一.struct
c形式1变量声明时需加struct关键字
#include <stdio.h> #include <string.h> struct SStudent { char cName[ 20 ]; int nAge; void (*pfnShowInfo)(struct SStudent s); }; void showName(struct SStudent s) { printf("----%s----\n",s.cName); } void showAge(struct SStudent s) { printf("----%d----\n",s.nAge); } void main() { struct SStudent s1; memset(s1.cName , 0 , sizeof( s1.cName) ); strcat( s1.cName , "SE0600"); s1.nAge = 15 ; s1.pfnShowInfo = showName; s1.pfnShowInfo(s1); s1.pfnShowInfo = showAge; s1.pfnShowInfo(s1); }
c形式2
使用typdef重定义类型
#include <stdio.h> #include <string.h> typedef struct SS{ char cName[ 20 ]; int nAge; void (*pfnShowInfo)(struct SS); //Type redefine not to take effect }SStudent; void showName(SStudent s) { printf("----%s----\n",s.cName); } void showAge(SStudent s) { printf("----%d----\n",s.nAge); } void main() { SStudent s1; memset(s1.cName , 0 , sizeof( s1.cName) ); strcat( s1.cName , "SE0600"); s1.nAge = 15 ; s1.pfnShowInfo = showName; s1.pfnShowInfo(s1); s1.pfnShowInfo = showAge; s1.pfnShowInfo(s1); }
C++形式
#include <iostream> #include <cstring> using namespace std; struct SStudent { char cName[20]; int nAge; void (*pfnShowInfo)(SStudent); void show(char *pcName); void show(int nAge){ cout<<"[Struct Function Call]Age : "<<nAge<<endl;} }; void show(SStudent s) { cout<<"[Function Pointer Call]Name : "<<s.cName<<endl; } void showAge(SStudent s) { cout<<"[Function Pointer Call]Age : "<<s.nAge<<endl; } void SStudent::show(char *pcName) { cout<<"[Struct Function Call]Name : "<<cName<<endl; } int main() { SStudent s1; memset( s1.cName , 0 , sizeof( s1.cName )); strcat( s1.cName , "SE0600"); s1.nAge = 15; s1.show(s1.cName); s1.show(s1.nAge); s1.pfnShowInfo = show; s1.pfnShowInfo(s1); s1.pfnShowInfo = showAge; s1.pfnShowInfo(s1); return 0; }
C++ stuct特性
C++ struct与C++ class极为类似,区别:
成员的默认访问权限
struct 默认是public
class 默认是 private
默认的继承
struct 默认是public
class默认是private
建议struct成员只包含基本数据类型,其它特性用class实现.
二.namespace
作用组织和重用代码,制定标识符的使用范围,解决同名冲突。
使用
在声明一个命名空间时,花括号内不仅可以包括变量,而且还可以包括以下类型:
变量(可以带有初始化)
常量
函数(可以是定义或声明)
结构体
类
模板
命名空间(在一个命名空间中又定义一个命名空间,即嵌套的命名空间)。
namespace nsl { const int RATE=0.08; //常量 doublepay; //变量 doubletax() //函数 {return a*RATE;} namespacens2 //嵌套的命名空间 {int age;} } 如果想输出命名空间nsl中成员的数据,可以采用下面的方法: cout<<nsl::RATE<<endl; cout<<nsl::pay<<endl; cout<<nsl::tax()<<endl; cout<<nsl::ns2::age<<endl; //需要指定外层的和内层的命名中间名
Sample
#include <iostream> namespace NSBus { const int nMAX_CAPCITY = 50; int nCurTripDistance = 0; void setTripDistance(int nTripDistance); int getTripDistance(){ return nCurTripDistance ; } } void NSBus::setTripDistance(int nTripDistance) { nCurTripDistance = nTripDistance; } namespace NSCar { const int nMAX_CAPCITY = 5; int nCurTripDistance = 0; void setTripDistance(int nTripDistance); int getTripDistance(){ return nCurTripDistance ; } } void NSCar::setTripDistance(int nTripDistance) { nCurTripDistance = nTripDistance; } namespace //匿名命名空间,作用域为当前文件作用域,可解决多文件类型重定义.相当于static { int nPersons = 100; } using namespace std; int main() { const int nMAX_CAPCITY = 100; cout<<"[NSBus] Max Capacity "<<NSBus::nMAX_CAPCITY f579 <<endl; cout<<"[NSCar] Max Capacity "<<NSCar::nMAX_CAPCITY<<endl; cout<<"[Main] Max Capacity "<<nMAX_CAPCITY<<endl; namespace NSAutoMobile = NSCar; //set namespace alias cout<<"[NSAutoMobile] Max Capacity "<<NSAutoMobile::nMAX_CAPCITY<<endl; using namespace NSBus; //set NSBus globle use nCurTripDistance = 5000; cout<<"[NSBus] TripDistance "<<NSBus::nCurTripDistance<<endl; return 0; }
三.string
四.vetor
vector是C++标准模板库中的部分内容,属于std命名域,头文件vector参考链接 http://blog.chinaunix.net/uid-26000296-id-3785610.html
声明(构造)
vector // 创建一个空的vector。 vector c1(c2) // 复制一个vector vector c(n) // 创建一个vector,含有n个数据,数据均已缺省构造产生 vector c(n, elem) // 创建一个含有n个elem拷贝的vector vector c(beg,end) // 创建一个含有n个elem拷贝的vector
成员函数
c.assign(beg,end) //将[begin; end)区间中的数据赋值给c c.assign(n,elem) //将n个elem的拷贝赋值给c。 c.at(idx) //传回索引idx所指的数据,如果idx越界,抛出out_of_range。 c.back() // 传回最后一个数据,不检查这个数据是否存在。 c.begin() // 传回迭代器中的第一个数据地址。 c.capacity() // 返回容器中数据个数。 c.clear() // 移除容器中所有数据。 c.empty() // 判断容器是否为空。 c.end() // 指向迭代器中末端元素的下一个,指向一个不存在元素。 c.erase(pos) // 删除pos位置的数据,传回下一个数据的位置。 c.erase(beg,end) //删除[beg,end)区间的数据,传回下一个数据的位置。 c.front() // 传回第一个数据。 get_allocator // 使用构造函数返回一个拷贝。 c.insert(pos,elem) // 在pos位置插入一个elem拷贝,传回新数据位置。 c.insert(pos,n,elem) // 在pos位置插入n个elem数据。无返回值。 c.insert(pos,beg,end) // 在pos位置插入在[beg,end)区间的数据。无返回值。 c.max_size() // 返回容器中最大数据的数量。 c.pop_back() // 删除最后一个数据。 c.push_back(elem) // 在尾部加入一个数据。 c.rbegin() // 传回一个逆向队列的第一个数据。 c.rend() // 传回一个逆向队列的最后一个数据的下一个位置。 c.resize(num) // 重新指定队列的长度。 c.reserve() // 保留适当的容量。 c.size() // 返回容器中实际数据的个数。 c1.swap(c2) swap(c1,c2) // 将c1和c2元素互换。同上操作。 operator[] // 返回容器中指定位置的一个引用。
遍历
循环控制
for( int i = 0 ; i < v.size() ; i++ ){ cout<<v[i]<<" "; //不做越界检查 cout<<v.at(i)<<" "; //越界抛出out_of_range异常 }
迭代器
for( vector<int>::iterator it != v.begin() ; i < v.end() ; i++ ) cout<<*it<<" ";
Sample
//===================================== // f0311.cpp // 若干个向量按长短排序 //===================================== #include<iostream> #include<fstream> #include<sstream> #include<vector> using namespace std; //------------------------------------- typedef vector<vector<int> > Mat; Mat input(); void selectionSort(Mat& a); void print(const Mat& a); void bubbleSort(Mat &a); //------------------------------------- int main() { Mat a = input(); cout<<"File Content : "<<endl; print(a); selectionSort(a); cout<<"selectionSort Result(ASC) : "<<endl; print(a); cout<<"bubbleSort Result(DESC) : "<<endl; bubbleSort(a); print(a); return 0; }//------------------------------------ Mat input() { ifstream in("aaa.txt"); Mat a; for(string s; getline(in, s); ){ vector<int> b; istringstream sin(s); //包含在SStream头文件中,流操作 for(int ia; sin>>ia; ) b.push_back(ia); a.push_back(b); } return a; }//------------------------------------ void bubbleSort( Mat &a ) { for( int i = 0 ; i < a.size() ; i++ ){ for ( int j = 0; j < a.size() - i - 1 ; j++) { if( a.at( j ).size() < a.at( j + 1 ).size() ) swap( a.at( j + 1 ) , a.at( j ) ); } } } void selectionSort(Mat &a) { for (int i = 0; i < a.size() - 1 ; i++) { int nMinSize = i ; for (int j = i + 1 ; j < a.size(); j++) { if( a.at( nMinSize ).size() > a.at( j ).size() ) nMinSize = j; } if( nMinSize != i ) swap( a.at( nMinSize ) , a.at( i ) ); } } void print(const Mat& a) { for(int i=0; i<a.size(); ++i){ for(int j=0; j<a.at(i).size(); ++j) cout<<a.at(i).at(j)<<" "; cout<<endl; } }
五.void *
void*表示“空类型指针”,与void不同,void*表示“任意类型的指针”或表示“该指针与一地址值相关,但是不清楚在此地址上的对象的类型”.为什么不用void表示任意类型的数据呢?
大家都知道,C/C++是静态类型的语言,定义变量就会分配内存,然而,不同类型的变量所占内存不同,如果定义一个任意类型的变量,如何为其分配内存呢?
所以,C、C++中没有任意类型的变量。但是,所有指针类型的变量,无论是int*、char*、string*、Student*等等,他们的内存空间都是相同的,所以可以定义“任意类型的指针”。
void*指针只支持几种有限的操作:
与另一个指针进行比较;向函数传递void指针或从函数返回void*指针;
给另一个void*指针赋值。不允许使用void*指针操作它所指向的对象,例如,不允许对void*指针进行解引用。不允许对void*指针进行算术操作
#include <iostream> int main() { using namespace std; void *pc = 0 ; //声明void(无类型或叫通用性)指针pc int i = 123; char c = 'a'; pc = &i; //将存放整型数123的变量i的地址赋给void型指针pc cout << *(int *) pc << endl; //输出指针值123,要进行整型数类型转换 pc = &c; //将存放字符a的变量c的地址赋给void型指针pc cout << *(char *) pc <<endl; //输出指针值a,要进行字符型数类型转换 return 0; }
六.类型转换
类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比如你可以把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成指向一个派生类对象的指针,这两种转换之间的差别是巨大的,但是传统的c语言风格的类型转换没有区分这些。还有一个缺点就是,c风格的转换不容易查找,他由一个括号加上一个标识符组成,而这样的东西在c++程序里一大堆.所以c++为了克服这些缺点,引进了4新的类型转换操作符。static_cast
编译期的转化,不能转换掉expression的const、volitale、或者__unaligned属性
所有内建类型对象之间的隐式转换都可用static_cast.
把空指针转换成目标类型的空指针用static_cast。
把任何类型的表达式转换成void类型用static_cast。
类层次间的上行转换和下行转换也可以用static_cast,但下行转换即当把基类指针或引用转换成子类表示时,由于没有动态类型检查,所以是不安全的.反之是安全的.
const_cast
编译期的转化,去除类型中的const 属性
dynamic_cast
运行期的转换,类层次间的上行转换和下行转换
dynamic_cast具有类型检查的功能,下行转换的效果跟static_cast是一样的,但下行转换比static_cast更安全。
dynamic_cast还支持交叉转换,两个类如果有共同的祖先,他们的指针就可以用dynamic_cast.
reinterpret_cast
任何指针都可以转换成其它类型的指针,可用于如char* 到 int*,或者One_class* 到 Unrelated_class* 等的转换,因此可能是不安全的。
七.运行时内存布局(Runtime memory layout)
一般而言,操作系统将程序装入内存后,将形成一个随时可以运行的进程空间,将进程空间分四个区域:名字 | 作用 |
---|---|
栈区(stack area) | 存放函数数据区(即局部数据区),它动态地反映了程序运行中的函数状态,系统自动分配释放。 |
堆区(heap area) | 动态内存,供程序随机申请使用。 |
代码区(code area) | 存放程序的执行代码,所谓执行代码就是索引了的一个个函数块代码,它由函数定义块的编译得到。 |
全局数据区(data area) | 存放全局数据、常量、文字量、静态全局量和静态局部量。 |
八.指针与引用(Reference)
指针限定指针常量:相对于指针常量而言,指针值不能修改,如 int const *p;
常量指针:指向常量的指针的简称。如 const int *p;
const int a = 78; int b = 10; int c = 18; const int *ip = &a; //const修饰指向的实体类型---常量指针 int *const cp = &b; //const修饰指针*cp-----指针常量 int const *dp = &b; //指针常量 const int* const icp = &c; //常量指针常量 *ip = 87; //错:常量指针不能修改指向的常量,*ip只能做右值 ip = &c; //ok:常量指针可以修改制针织 *cp = 81; //ok:指针常量可以修改指向的实体 cp = &b; //错:指针常量不能修改指针值,即便是同一个地址 *icp = 33; //常量指针常量不能修改指向的常量 icp = &b; //常量指针常量不能修改指针值 int d = *icp; //ok
引用(Reference)
从逻辑上理解,引用就是一个别名(alias),引用定义时必须初始化.引用相当于一个隐形指针。
int someInt = 5; int &rInt = someInt; sample: //===================================== // f0315.cpp // 引用及其地址 //===================================== #include<iostream> using namespace std; //------------------------------------- int main(){ int int1 = 5; int& rInt = int1; cout<<"&int1: "<<&int1<<" int1: "<<int1<<endl; cout<<"&rInt: "<<&rInt<<" rInt: "<<rInt<<endl; int int2 = 8; rInt = int2; cout<<"&rInt: "<<&rInt<<" rInt: "<<rInt<<endl; //rInt的值改变,但是地址没变 }//====================================
九.全局数据(Global Data )
全局数据就是在任何函数的外部声明或者定义的,起到所有函数都可以访问它的作用.“一次定义原则”。.多次声明,但是只有有一次定义,声明形式是在定义形式前加extern.
全局数据在程序启动时初始化为0,如果定义时未初始化,默认为0.
十.静态数据(Static Data)
静态全局数据(Static Global Data)内部链接性:只在本文件内可见,在其它程序文件中不可见.
静态局部数据(static Local Data)
静态局部变量驻留在全局数据区,默认初始值为0,仅在第一次调用时被初始化.
sample
//===================================== // f0709.cpp // 静态局部数据 //===================================== #include<iostream> using namespace std; void func(); int n = 1; int main() { int a = 0 , b = -10; cout<<"a="<<a<<",b="<<b<<",n="<<n<<endl; func(); cout<<"a="<<a<<",b="<<b<<",n="<<n<<endl; func(); } void func() { static int a = 2; int b = 5; a += 2; b += 5; n += 12; cout<<"a="<<a<<",b="<<b<<",n="<<n<<endl; } /*outout: a=0,b=-10,n=1 a=4,b=10,n=13 a=0,b=-10,n=13 a=6,b=10,n=25 */
相关文章推荐
- firebird的数据类型(datatype)
- Java Object to Data Model Data Type Mapping, java数据类型与数据库数据类型的对应
- Data type mismatch in criteria expression. 条件表达式中数据类型不匹配
- (JAVA SE 学习笔记)Java.SE.第003讲.原生数据类型使用陷阱.Pitfall.of.Primitive.Data.Type
- MFC数据类型(Data Type)
- 获取Oracle表结构时,两种OleDb驱动得到的列数据类型“DATA_TYPE”值的类型不同
- 如何在EA(Enterprise Architect)中自定义数据类型(Data Type)
- 第二节:原生数据类型 Primitive Data Type
- firebird的数据类型(datatype)
- CORBA Programming with TAO - 3.IDL Data Type(数据类型与Mapping)
- (JAVA SE 学习笔记)Java.SE.第002讲.原生数据类型 (Primitive Data Type)
- 【转载】MFC数据类型(Data Type)
- MFC数据类型(Data Type)
- data type : 数据类型
- Data type mismatch in criteria expression. 标准表达式中数据类型不匹配
- sql server数据类型在SqlDataType的匹配
- CORBA Programming with TAO - 3.IDL Data Type(数据类型与Mapping)
- CORBA Programming with TAO - 3.IDL Data Type(数据类型与Mapping)例子常见问题篇
- MFC数据类型(Data Type)
- C++不同数据类型的取值范围(Data Type Ranges )