您的位置:首页 > 编程语言 > C语言/C++

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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++Notes