C++中共有四种存储类别标识符:auto/static/register/extern

1.auto

函数或分程序内定义的变量(包括形参)可以定义为auto(自动变量)。如果不指定存储类别,则隐式定义为auto。

例如,函数类有如下定义:

  auto int x , y ;

等价于:

  int x , y ;

2.static

除了形参,可以将局部变量和全局变量定义为静态变量。用static标识符。

static int a;//a是全局静态变量

f()

{static int b = 1;}//b是局部静态变量

与auto不同,static变量的生存期是程序开始运行到运行结束(auto变量生存期是函数调用结束)。

若定义静态变量时没有对其赋初值,系统自动赋初值0;若赋初值,则仅在编译时赋初值一次,程序运行后不再给变量赋初值。当上一次调用局部静态变量所在的函数时,该变量的值继续有效(为上次函数调用结束时保留的值)。

3.extern

在函数外定义的变量如果没有用static声明,则是extern外部变量。外部变量只能隐式定义为extern,不能显示定义。

对外部变量声明时,系统不分配存储空间。

#include <iostream>

using namespace std;
int x = , y = ;//定义外部变量
void f1()
{
extern char c1 , c2 ;//声明外部变量
cin>>c1>>c2;
}
char c1 , c2 ;//定义外部变量 int main()
{
int m , n ;
f1();
cout <<c1<<"+"<<c2<<"="<<x+y<< endl;
return ;
}

结果是这样:

注意,如果把extern去掉了,再输入xy,回车,会出现:

因为c1,c2的作用域只在f1函数里面。如果不用extern,想达到第一幅的效果,只要把

char c1 , c2 ;//定义外部变量

这句拿到f1()前面就行了。

4.register

寄存器变量的值保存在CPU的寄存器中,读写速度更快。随着计算机硬件性能提高,现在寄存器变量使用得比较少了。

------------------------------------------------

指针和引用:

指针 = *指针变量

&取地址运算符,返回其指向的变量或数组元素的地址。

&取地址

*取目标变量

这两个运算符互为逆运算,如图(Page129,《C++程序设计》,姚琳,人民邮电出版社):

赋值运算:

注意,

可以把一个已经初始化的指针值非给另一指针,例如:

float x, *p = &x, *q = p;

可以把*理解成跟float连在一起。

这样,q和p有相同的地址,指向x。

引用(<数据类型名> &引用名=变量名;):

补充:改错题:

void test(char * OldName){
char[] NewName;
int len=;
for(;OldName[len] != '\0';len++){ NewName[len] = OldName[len]; }
return;
}

两个错误,

1.C语言中的数组定义跟Java还是有区别的,不能像上面那样定义,而要写成char NewName[30];而且NewName后面不能有空格;

2.OldName的长度需要设定一下,不然超过30之后,NewName没有那么多元素,出现溢出错误。

Mr.Yin:对于其中指针的理解,其实char NewName[30];  比如NewName[0]就是下图的0x01元素,那么NewName就是0x00ff,也就是一个地址。

 
 
 
0x01

0x00ff

同理,有:

p[i] = *(p+i)

-----------------2016年1月26日 带成瑞------------------------------------------------------

 &p[i] = p+i 

类的定义:

跟Java不同,C++中类定义结束之后,要加分号。

class Student
{
public :
void printStudent(); private:
int id;
char* name ;
char sex;
};

其中,成员函数printStudent()以函数声明的形式出现。成员函数的具体实现可以放在类定义的外部:

void Student::printStudent()
{
cout<<"id:"<<id<<","<<"name:"<<name<<","<<"sex:"<<sex<<endl;
}

成员函数的定义和一般函数的定义区别在于「类名」和「::」构成作用域,表示出该成员函数属于的类。

一般来说,类的成员函数都放在类外进行。

一个基本原则:尽量将成员数据和成员函数设计成私有访问控制属性,体现类的「封装性」。

类的访问属性private和public的访问规则:

静态成员和友元:

静态成员数据是一个类的所有对象共享的数据成员,静态成员数据与一般数据的区别在于:对于静态成员数据,该类的每个对象都共享唯一的数据,即它只存在一份拷贝,而对于一般成员数据,该类的每个对象都独立简历自己的一个副本,以保存各自特定的值。因此,静态成员数据属于类级别的成员,而一般成员数据属于对象级别的成员。

初始化静态成员数据必须在类外进行。

比如:

class Student
{
public :
void printStudent(); private:
int id;
char* name ;
char sex;
};

其中,成员函数printStudent()以函数声明的形式出现。成员函数的具体实现可以放在类定义的外部

void Student::printStudent()
{
cout<<"id:"<<id<<","<<"name:"<<name<<","<<"sex:"<<sex<<endl;
}

成员函数的定义和一般函数的定义区别在于「类名」和「::」构成作用域,表示出该成员函数属于的类。

一般来说,类的成员函数的定义都放在类外进行。

一个基本原则:尽量将成员数据和成员函数设计成私有访问控制属性,体现类的「封装性」。

class Student
{
public:
... private:
static int count;//静态成员数据的定义
}
int Student::count=;//静态成员数据的初始化

静态成员函数是一个类所有对象共享的成员函数。静态成员函数也成为类成员函数(因为静态成员函数和静态成员数据属于类层次,而一般成员函数和一般成员数据属于对象层次。)

没有对象生成时,静态成员函数中是不能访问一般成员函数和一般成员数据的。

静态成员函数放在类内声明,类外初始化(事实上一般来说,成员函数的初始化都放在类外进行)。

友元:

静态成员数据提供了在一个类的所有对象之间共享数据的机制。

而友元则是不同类的成员函数之间、类的成员函数和一般函数之间进行数据共享的机制,破坏了封装性和数据隐藏性。不提倡使用。友元可以定义在函数级别或是类级别。

常对象(类名 const 对象名;):

对于基本数据类型的变量,可以定义符号常量,其值在程序运行过程中保持不变。

对于「类」这种自定义数据类型,同样可以定义一种对象,使得数据成员保持不变,也就是常对象。

常成员:

(1)常成员数据:可以通过定义常成员数据使得部分成员数据的值保持不变。

const 数据类型 变量名;

一般符号常量的定义和初始化是在同一语句中实现的,而常成员数据的初始化通常是分开进行的,在类的初始化列表处进行。

class Student
{
public:
Student(int pId , Char*pName , int pAge);
private:
const int id;
char* name;
int age;
};

Student::Student(int pId, char* pName, int pAge):id(pId)//这个构造函数后面的id(pId也可以理解为id变量的构造函数,在这里初始化。----Mr.Yin)

(2)常成员函数:

数据类型 函数名(形参列表) const;

1.常成员函数不能调用一般成员函数。

2.const可作为重载条件。如void printAdmin()和void printAdmin() const构成一对重载函数。

3.常对象只能定义常成员函数,不能访问一般函数。

继承与派生:

定义派生类的一般方式:

class 派生类名:继承方式 基类1,继承方式 基类2,..继承方式 基类n

{

//派生类新增的成员声明

};

例如:设已有基类base1和base2,定义派生类deriver:

class deriver: public base1 , private base2

{

private:

int m_derdate;

public:

void derfun();

}

以上定义的派生类deriver以共有方式继承基类base1,以私有方式继承基类base2,并且新增加了两个成员。

派生类自己增加的成员,完成两个需求:修改基类成员和描述新的特征和方法。

派生类修改基类的成员,通过在派生类中声明一个与基类成员同名的新成员来实现(同Java中的override)。

继承的访问控制(拍书狂魔):

主要看下划线和最下面的表格:

看public和protected:

区别在第三点:派生类以外的其他函数不可以通过派生类的对象访问从基类继承的公有成员。我理解的意思也就是,派生类不能作为一个媒介,让其他函数通过这个派生类来调用基类中的成员。

多重继承的二义性和虚基类

基类base的成员,先被继承到派生类Fderiver1,Fderiver2,然后又要被继承到派生类Sderiver,则爱生类Sderiver中有base的成员的两份拷贝。出现ambiguous错误,也就是二义性。

为解决这个问题,可以将共同基类设置成虚基类,这样在创建派生类对象时,虚基类的构造函数只调用一次,虚基类的成员在第三层派生对象中只有一份拷贝。

上例中,首先将base声明为虚基类:

class Fderiver1:virtual public base

{

//..原来的代码

};

class Fderiver2:virtual public base

{

//..原来的代码

};

其次,对第二级派生类Sderiver的构造函数作修改:

Sderiver(int attrib,int data):base(data),Fderiver1(value,data),Fderiver2(number,data)

{

//...

}
 

(按:上面的构造函数后面的冒号:base(data)的用法是初始化,初始化跟赋值不同,初始化在分配内存的时候直接赋值,是一步操作;赋值是两步操作。)

编译系统只执行其中的base(data)调用对虚基类构造函数的调用,而忽略通过Fderiver1(value,data)和Fderiver2(number,data)对虚基类构造函数的调用。

--------------------------------------------

多态性与虚函数

多态性是指相同的函数名或者运算符在不同场合下使用,能表现出不同的行为或特征。

标准模板库

标准模板库(Standard Template Library,STL)主要内容包括容器、算法和迭代器。

容器有7种,分别是:向量,栈,列表,双端队列,集合,多重集合,映射。

向量:大小可变,可以像数组一样直接访问(at得到编号位置的数据),也可以像链表一样顺序访问。

一维向量的数据存取:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
int i = ;
vector<int> v ;//定义元素为整形的一维变量
for(i = ; i < ; i++)
{
v.push_back(i);//push_back在容器的最后添加一个数据
}
for(i = ; i<v.size() ; i ++)
{
cout<<v[i]<<" ";
}
cout<<endl;
return ;
}

程序运行结果:

0 1 2 3 4 5 6 7 8 9

其中,上面的

for(i =  ; i<v.size() ; i ++)
{
cout<<v[i]<<" ";
}

用迭代器实现:

vector<int>::iterator iter;
for(iter = v.begin; iter!=v.end(); iter++)//begin获取容器头指针,end获取尾指针+1
{
cout<<*iter<<" ";
}

[C++]变量存储类别,指针和引用,类与对象,继承与派生的一些摘要的更多相关文章

  1. C++变量存储类别和内存四区

    变量存储类别 变量声明/定义的一般形式: 存储类别 数据类型 变量名 存储类别指的是数据在内存中存储的方法.存储方法分为静态存储和动态存储两大类.标准C语言为变量.常量和函数定义了4种存储类型:ext ...

  2. C语言中存储类别又分为四类:自动(auto)、静态(static)、寄存器的(register)和外部的(extern)。

    除法运算中注意: 如果相除的两个数都是整数的话,则结果也为整数,小数部分省略,如8/3 = 2:而两数中有一个为小数,结果则为小数,如:9.0/2 = 4.500000. 取余运算中注意: 该运算只适 ...

  3. c++中变量、变量名、变量地址、指针、引用等含义

    首先了解内存,内存就是一排房间,编号从0开始,0,1,2,3,4,5...... 房间里面一定要住人,新人住进去了,原来的人就走了:不管你住不住,里面都有人. 编号就是地址.里面的人就是内容,为了我们 ...

  4. 类与对象 && 继承

      以下是本人的对类与对象.继承的一些理解,如有错误之处万望谅解,如有朋友愿意指正,十分乐意,万分感谢!   类与对象     类与对象是学习编程的基础(大概吧),那么何为类?何为对象呢?   一.简 ...

  5. python3 之 面向对象(类)、继承、派生和多态

    类提供了一种 组合数据和功能 的方法.创建一个新类意味着:创建一个新 类型  的对象,从而允许创建一个该类型的新 实例. 每个类的实例可以拥有: 保存自己状态的属性. 一个类的实例也可以有改变自己状态 ...

  6. Java自学-类和对象 继承

    什么是 Java的 继承 ? 在LOL中,武器是物品的一种,也是有名称和价格的 所以在设计类的时候,可以让武器继承物品,从而继承名称和价格属性 步骤 1 : 物品类Item 物品类Item 有属性 n ...

  7. (转)c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考

    昨天去面试一家公司,面试题中有一个题,自己没弄清楚,先记录如下: class D { public: void printA() { cout<<"printA"< ...

  8. C++对象的复制——具有指针成员的类的对象的复制

    //smartvessel@gmail.com class Table{ Name * p; size_t sz; publish: Table(size_t s = 15){p = new Name ...

  9. C++变量作用域、生存期、存储类别

    写C.C++代码的小伙伴一定在头疼变量的作用域.生存期.存储类别问题.什么静态.外部.寄存器.局部.全局搞得一头雾水.今天咱们就来梳理一下他们的变态关系(什么不得了的事情???) 1.变量的作用域 说 ...

随机推荐

  1. Mac环境下安装运行splash

    http://blog.csdn.net/chenhy8208/article/details/69391097 最近需要使用scrapy爬虫做一些开发,用到了splash.我本机是mac环境,跳着看 ...

  2. python为不同的对象如何分配内存的小知识

    id方法的返回值就是对象的内存地址. python中会为每个出现的对象分配内存,哪怕他们的值完全相等(注意是相等不是相同).如执行a=2.0,b=2.0这两个语句时会先后为2.0这个Float类型对象 ...

  3. 老毛桃winpe优盘启动系统个性修改全攻略

    PE优盘系统也有很多:大白菜.老毛桃.深度.通用PE工具箱.U大师.电脑店……这些PE优盘系统大多都会捆绑软件安装.更改主页等,一不小心,你就中招.虽然有些是可以自己去取消,但是启动画面还是带有各种L ...

  4. USACO 1.2 Milking Cows (枚举)

    标记数组(哈希) 1e6的范围,开一个char数组全然能够,有人为1,无人为0,注意边界就可以.最后线性扫描就可以. 时间复杂度,应该是O(n),n为最后结束的时间. 缺点就是--比較慢 /* ID: ...

  5. table 设置边框

    本文引自:https://www.cnblogs.com/leona-d/p/6125896.html 示例代码: <!DOCTYPE html> <html lang=" ...

  6. linux查找文件夹下的全部文件里是否含有某个字符串

    查找文件夹下的全部文件里是否含有某个字符串  find .|xargs grep -ri "IBM"  查找文件夹下的全部文件里是否含有某个字符串,而且仅仅打印出文件名称  fin ...

  7. kubernetes对象之Ingress

    系列目录 概述 向外网暴露集群内服务,以使客户端能够访问,有以下几种方法,本文重点描述Ingress. LoadBalancer LoadBalancer一般由云服务供应商提供或者用户自定义,运行在集 ...

  8. PHP 7.1.5编译安装

    1. 安装基础组件 yum install -y libxml2 libxml2-devel bzip2 bzip2-devel curl-devel libjpeg libjpeg-devel li ...

  9. erlang取列表中某个值的位置

    有个需求,比如在一个列表中,取出一个元素的位置,如果出现重复都取出.例如:List = [2,3,10,324,88,29,12],可以求大于某个值的位置,也可以取某个值的位置. 废话少说,直接上代码 ...

  10. ffmpeg mediacodec 硬解初探

    ffmpeg mediacodec 硬解初探 1编译: ffmpeg自3.1版本加入了android mediacodec硬解支持,解码器如图 硬件加速器如图(还不清楚硬件加速器的功能) 编译带h26 ...