一、static成员变量和static成员函数

1.普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享

2.普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。

3.因此静态成员不需要通过对象就能访问

4.静态成员变量本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。静态成员函数本质上是全局函数。

5.设置静态成员这种机制的目的是将和某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。

注意:

  1.必须在定义类的文件中对静态成员变量进行一次说明或者初始化,否则编译能通过,但链接不能通过。

  2.在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。

二、this指针和静态成员函数

1.静态成员函数中不能使用this指针

  因为静态成员函数并不具体作用于某个对象。因此,静态成员函数的真实的参数的个数,就是程序中写出的参数个数。

三、关于const的全部用法

1.常量对象

  如果不希望某个对象的值被改变,则定义该对象的时候可以在前面加const关键字。

2.常量成员函数

  在类的成员函数说明后面可以加const关键字,则该成员函数成为常量成员函数。

  常量成员函数执行期间不应修改其所作用的对象。因此在常量成员函数中不能修改成员变量的值(静态成员变量除外),也不能调用同类的非常量成员函数(静态成员函数除外)。

注意:

  两个成员函数,名字和参数表都一样,但是一个是const,一个不是,算重载。

3.常引用

  引用前面可以加const关键字,成为常引用。不能通过常引用,修改其引用的变量。

四、非引用的函数返回值不可以作为左值使用。

五、public继承的赋值兼容规则

1.派生类的对象可以赋值给基类对象。

2.派生类的对象可以初始化基类的引用。

3.派生类的对象的地址可以赋值给基类指针。

六、C++如下运算符不能重载:
“.”    ".*"      "::"     "?:"     sizeof

七、函数模板调用顺序:

1.先找参数完全匹配的普通函数(非自由模板实例化而得的函数)

2.再找参数完全匹配的的模板函数

3.再找实参经过自动类型转换后能够匹配的普通函数

4.上面的都找不到,则报错

备注:

赋值兼容规则引起函数模板中类型参数的二义性

 template <class T>

 T func(T a, T b) {

   cout << "a = " << a << endl;

   return a;

 }

 func(, );   // ok: replace T with int

 func(5.8, 8.4); // ok: replace T with double

 func(, 8.4);  // error: replace T with int or double ??

针对上面问题的解决方案如下:

可以在函数模板中使用多个类型参数,可以避免二义性

 template <class T1, class T2>

 T1 func(T1 a, T2 b) {

   cout << "a = " << a << endl;

   return a;

 }

 func(, );   // ok: replace T1 and T2 with int

 func(5.8, 8.4); // ok: replace T1 and T2 with double

 func(, 8.4);  // ok: replace T1 with int, T2 with double

八、构造函数

1.复制构造函数(copy constructor)

  1)复制构造函数只有一个参数,即对同类对象的引用。

  2)形如 X::X( X & )或者X::X( const X & ),二选一,后者能以常量对象作为参数

  3)如果没有定义复制构造函数,那么编译器生成默认复制构造函数。默认的复制构造函数完成复制功能。

  备注:如果定义了自己的复制构造函数,则默认的复制构造函数不再存在。

      不允许有形如X::X ( X )的构造函数

class CSample{
CSample( CSample cs) {
} // 错,不允许这样的构造函数
};

2.复制(拷贝)构造函数起作用的三种情况

  1) 当用一个对象去初始化同类的另一个对象时。

 Complex c2(c1);
Complex c2 = c1; // 初始化语句,非赋值语句

  2)如果某函数有一个参数是类A的对象,那么该函数被调用时,类A的复制构造函数将被调用。

 class A {
public:
A(){};
A( A &a) {
cout << "Copy constructor called" << endl;
}
}; void Func(A a1) { } int main(void)
{
A a2;
Func(a2);
return ;
}

程序输出结果:

Copy constructor called

  3)如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数将被调用:

 class A {
public:
int v;
A(int n) { v = n; }
A( const A &a ) {
v = a.v;
cout << "Copy constructor called" << endl;
}
}; A Func() {
A b();
return b;
} int main(void) {
cout << Func().v << endl;
return ;
} // 输出结果:
Copy constructor called

3.类型转换构造函数

类型转换构造函数只有一个参数,它不同于复制构造函数。

编译系统会自动调用转换构造函数,建立一个临时对象/临时变量

 class Complex{
public:
double real, imag; Complex(int i) { // 类型转换构造函数
cout << "IntConstructor called" << endl;
real = i;
imag = ;
}
Complex(double r, double i) {
real = r;
imag = i;
}
}; int main(void) { Complex c1(, );
Complex c2 = ;
c1 = ;
cout << c1.real << "," << c1.imag << endl;
return ;
} // 输出:
IntConstructor called
IntConstructor called
,

Complex(int)这个构造函数就是类型转换构造函数。可以看出,该构造函数一共被调用了两次。第一次来自于对c2的初始化,第二次来自于第20行的赋值语句。

这条赋值语句的等号两边类型是不匹配的,之所以不会报错,就是因为Complex(int)这个类型转换构造函数能够接受一个整型参数。因此,编译器在处理这条赋值语句的时候,

会在等号右边自动生成一个临时的Complex对象,该临时对象以9为实参,用Complex(int)这个构造函数初始化,然后再将这个临时对象的值赋给c1,也可以说是9被自动转换成一个

Complex对象然后再赋值给c1。要注意,第19行是初始化语句,而不是赋值语句。所以,不会将12转换成一个临时对象,而是直接以12作为参数调用Complex(int)构造函数来初始化c2。

九、私有成员的访问权限:

类的成员函数内部,可以访问:

  1)当前对象的全部属性,函数

  2)同类其他对象的全部属性,函数

类的成员函数以外的地方:

  1)只能够访问该类对象的公有成员

十、静态成员变量static

普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。sizeof运算符不会计算静态成员变量。

普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。因此,静态成员不需要通过对象就能访问。

静态成员的访问:

1) 类名::成员名

  CRectangle::PrintTotal();

2) 对象名.成员名

  CRectangle r; r.PrintTotal();

3) 指针->成员名

  CRectangle *p = &r; p->PrintTotal();

4) 引用.成员名

  CRectangle &ref = r;  int n = ref.nTotalNumber;

静态成员变量,本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。

静态成员函数本质上是全局函数。

设置静态成员这种机制的目的是将和某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。

 class CRectangle
{
private:
int w, h;
static int nTotalArea;
static int nTotalNumber;
public:
CRectangle(int w_,int h_);
~CRectangle();
static void PrintTotal();
}; CRectangle::CRectangle(int w_,int h_) {
w = w_;
h = h_;
nTotalNumber ++;
nTotalArea += w * h;
} CRectangle::~CRectangle() {
nTotalNumber --;
nTotalArea -= w * h;
} void CRectangle::PrintTotal() {
cout << nTotalNumber << "," << nTotalArea << endl;
} int CRectangle::nTotalNumber = ;
int CRectangle::nTotalArea = ;
// 必须在定义类的文件中对静态成员变量进行一次说明
//或初始化。否则编译能通过,链接不能通过。
int main()
{
CRectangle r1(,), r2(,);
//cout << CRectangle::nTotalNumber; // Wrong , 私有
CRectangle::PrintTotal();
r1.PrintTotal();
return ;
} // 输出:
,
,

注意事项:

在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。

 void CRectangle::PrintTotal()
{
cout << w << "," << nTotalNumber << "," << nTotalArea << endl; //wrong
} CRetangle::PrintTotal(); //解释不通,w 到底是属于那个对象的?

在CRectangle类的写法中,有何缺陷?

 CRectangle::CRectangle(int w_,int h_) {
w = w_;
h = h_;
nTotalNumber ++;
nTotalArea += w * h;
} CRectangle::~CRectangle() {
nTotalNumber --;
nTotalArea -= w * h;
} void CRectangle::PrintTotal() {
cout << nTotalNumber << "," << nTotalArea << endl;
}

在使用CRectangle类时,有时会调用复制构造函数 生成临时的隐藏的CRectangle对象

  调用一个以CRectangle类对象作为参数的函数时,

  调用一个以CRectangle类对象作为返回值的函数时

临时对象在消亡时会调用析构函数,减少nTotalNumber 和 nTotalArea的值,可是这些临时对象在生成时却没有增加 nTotalNumber 和 nTotalArea的值。

解决办法:为CRectangle类写一个复制构造函数。

 CRectangle :: CRectangle(CRectangle & r ) {
w = r.w;
h = r.h;
nTotalNumber ++;
nTotalArea += w * h;
}

参考:

www.coursera.org上的pku公开课C++程序设计

《新标准C++程序设计教程》,郭炜

C++基本语法的更多相关文章

  1. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  2. Swift与C#的基础语法比较

    背景: 这两天不小心看了一下Swift的基础语法,感觉既然看了,还是写一下笔记,留个痕迹~ 总体而言,感觉Swift是一种前后端多种语言混合的产物~~~ 做为一名.NET阵营人士,少少多多总喜欢通过对 ...

  3. 探索C#之6.0语法糖剖析

    阅读目录: 自动属性默认初始化 自动只读属性默认初始化 表达式为主体的函数 表达式为主体的属性(赋值) 静态类导入 Null条件运算符 字符串格式化 索引初始化 异常过滤器when catch和fin ...

  4. [C#] 回眸 C# 的前世今生 - 见证 C# 6.0 的新语法特性

    回眸 C# 的前世今生 - 见证 C# 6.0 的新语法特性 序 目前最新的版本是 C# 7.0,VS 的最新版本为 Visual Studio 2017 RC,两者都尚未进入正式阶段.C# 6.0 ...

  5. Velocity初探小结--velocity使用语法详解

    做java开发的朋友一般对JSP是比较熟悉的,大部分人第一次学习开发View层都是使用JSP来进行页面渲染的,我们都知道JSP是可以嵌入java代码的,在远古时代,java程序员甚至在一个jsp页面上 ...

  6. node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法

    1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...

  7. C#语法糖大汇总

    首先需要声明的是"语法糖"这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换:而且可以提高开发编码的效率,在性能上也不会带来损失.这让java开发人员羡慕 ...

  8. 值得注意的ibatis动态sql语法格式

    一.Ibatis常用动态sql语法,简单粗暴用一例子 <select id="iBatisSelectList" parameterClass="java.util ...

  9. Flex 布局教程:语法篇

    作者: 阮一峰 网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便 ...

  10. postgresql 基本语法

    postgresql数据库创建/修改/删除等写入类代码语法总结: 1,创建库 2,创建/删除表 2.1 创建表 create table myTableName 2.2 如果表不存在则创建表 crea ...

随机推荐

  1. 软件卸载工具 Uninstall Tool 3.5.1 中文破解版

    Uninstall Tool 是一个小巧.安全.快速.强大的软件卸载删除工具,它支持在使用软件本身的卸载程序卸载完毕后,再扫描软件残留的注册及其它残余文件,将其彻底在系统删除!安装监视器可以监视每个应 ...

  2. 修改Windows/Ubuntu/Mint多系统的默认启动顺序

    打开该配置文件 sudo gedit /etc/default/grub 其中的“GRUB_DEFAULT=0”就是设置的默认启动项了.GRUB启动项是按照启动菜单依次使用数字进行索引了,起始数字为0 ...

  3. noip2016十连测round2

    A: Divisors 题意:给定 m 个不同的正整数 a 1 ,a 2 ,...,a m ,请对 0 到 m 每一个 k 计算,在区间 [1,n] 里有多少正整数 是 a 中恰好 k 个数的约数. ...

  4. bc#54 div2

    用小号做的div2 A:竟然看错了排序顺序...白白WA了两发 注意读入一整行(包括空格):getline(cin,st) [gets也是资瓷的 #include<iostream> us ...

  5. 常见linux命令释义(第八天)—— Bash Shell 的操作环境

    换了新公司,公司的领导很不错.自己感受比较多的地方是,自己的工作效率明显比以前高了.以前会对频繁变动的需求十分不耐烦,现在接到需求后会仔细的思考,进行整体构建.即使以后需求有变动,也能够比较轻易的在原 ...

  6. Kafka实战-Flume到Kafka

    1.概述 前面给大家介绍了整个Kafka项目的开发流程,今天给大家分享Kafka如何获取数据源,即Kafka生产数据.下面是今天要分享的目录: 数据来源 Flume到Kafka 数据源加载 预览 下面 ...

  7. 15个JavaScript本地存储技术的函数库和工具

    当构建更复杂的JavaScript应用程序运行在用户的浏览器是非常有用的,它可以在浏览器中存储信息,这样的信息可以被共享在不同的页面,浏览会话. 在最近的过去,这将有可能只被cookies文本文件保存 ...

  8. 4、JavaScript

    一.JavaScript的概念:是基于对象和事件的脚本语言. 1.特点: a).安全性. b).跨平台性(只要可以解释JS的浏览器就可以执行,和平台无关) 2.JavaScript与Java的区别: ...

  9. [Python] 利用Django进行Web开发系列(二)

    1 编写第一个静态页面——Hello world页面 在上一篇博客<[Python] 利用Django进行Web开发系列(一)>中,我们创建了自己的目录mysite. Step1:创建视图 ...

  10. 封装自己的Common.js工具库

    Code/** * Created by LT on 2013/6/16. * Common.js * 对原生JS对象的扩展 * Object.Array.String.Date.Ajax.Cooki ...