1、构造函数、析构函数和变量的生存期

构造函数在对象生成时会被调用,析构函数在对象消亡时会被调用。

程序示例分析:

(1)

#include<iostream>
using namespace std;
class Demo {
int id;
public:
Demo(int i) { //类型构造函数
id = i;
cout << "id=" << id << " constructed" << endl;
}
~Demo() { //析构函数
cout << "id=" << id << " destructed" << endl;
}
};
Demo d1(); //全局变量,在main之前初始化
void Func()
{
static Demo d2();//静态局部变量,func结束消亡
Demo d3();
cout << "func" << endl;
}
int main() {
Demo d4();
d4 = ;
cout << "main" << endl;
{ Demo d5(); //局部变量的作用域和生存期都只到离它最近的,且将其包含在内的那一对“{}”中的“}”为止
}
Func(); //引发析构函数
cout << "main ends" << endl;
return ;
}

输出结果:

id= constructed
id= constructed
id= constructed
id= destructed
main
id= constructed
id= destructed
id= constructed
id= constructed
func
id= destructed
main ends
id= destructed
id= destructed
id= destructed

(2)

#include <iostream>
using namespace std;
class CMyclass {
public:
CMyclass() {};
CMyclass( CMyclass & c)
{
cout << "copy constructor" << endl;
}
~CMyclass() { cout << "destructor" << endl; }
};

输出结果:

copy constructor
fun
destructor //参数消亡
test
copy constructor
destructor // 返回值临时对象消亡
destructor // 局部变量消亡
destructor // 全局变量消亡

2、复制构造函数在不同编译器中的表现

class A {
public:
int x;
A(int x_):x(x_)
{ cout << x << " constructor called" << endl; }
A(const A & a ) { //本例中dev需要此const其他编译器不要
x = + a.x;
cout << "copy called" << endl;
}
~A() { cout << x << " destructor called" << endl; }
};
A f( ){ A b(); return b; }
int main( ){
A a();
a = f();
return ;
}

Visual Studio输出结果:

 constructor called
constructor called
copy called
destructor called
destructor called
destructor called

Dev C++输出结果:

 constructor called
constructor called
destructor called
destructor called

说明Dev出于优化目的并未生成返回值临时对象。 VS无此问题

3、静态成员变量和静态成员函数

(1)概念

静态成员:在说明前面加了static关键字的成员。

class CRectangle
{
private:
int w, h;
static int nTotalArea; //静态成员变量
static int nTotalNumber; //静态成员变量
public:
CRectangle(int w_, int h_);
~CRectangle();
static void PrintTotal(); //静态成员函数
};

普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享。普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。因此静态成员不需要通过对象就能访问。

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

sizeof 运算符不会计算静态成员变量。

class CMyclass {
int n;
static int s;
};

sizeof( CMyclass ) 等于 4

(2)如何访问静态成员

①类名::成员名

CRectangle::PrintTotal();

②对象名.成员名

CRectangle r;
r.PrintTotal();

③指针->成员名

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

④引用.成员名

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

(3)静态成员示例

考虑一个需要随时知道矩形总数和总面积的图形处理程序可以用全局变量来记录总数和总面积用静态成员将这两个变量封装进类中,就更容易理解和维护

#include<iostream>
using namespace std;
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 ;
}

输出结果:

,
,

此CRectangle类写法, 有何缺陷?

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

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

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

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

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

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

(4)为什么在静态成员函数中,不能访问非静态成员变量, 也不能调用非静态成员函数?

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

《新标准C++程序设计》3.3-3.4(C++学习笔记7)的更多相关文章

  1. 《新标准C++程序设计》4.5(C++学习笔记15)

    实例:长度可变的整型数组类 int main() { //要编写可变长整型数组类,使之能如下使用: CArray a; //开始里的数组是空的 ; i < ; ++i) a.push_back( ...

  2. 《新标准C++程序设计》4.6(C++学习笔记16)

    重载流插入运算符和流提取运算符 流插入运算符:“<<” 流提取运算符:“>>” cout 是在 iostream 中定义的,ostream 类的对象. “<<” 能 ...

  3. 《新标准C++程序设计》4.4(C++学习笔记14)

    运算符重载为友元函数 一般情况下,将运算符重载为类的成员函数,是较好的选择. 但有时,重载为成员函数不能满足使用要求,重载为普通函数,又不能访问类的私有成员,所以需要将运算符重载为友元. class ...

  4. 《新标准C++程序设计》4.1(C++学习笔记12)

    运算符重载的概念和原理 一.运算符重载的需求 C++预定义的“+.-. * ./.%. ^ .&.~.!.|. = .<< >>.!= ”等运算符,只能用于基本数据类型 ...

  5. 《新标准C++程序设计》3.8(C++学习笔记10)

    友元 友元分为友元函数和友元类两种. 一.友元函数 在定义一个类的时候,可以把一些函数(包括全局函数和其它类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对 ...

  6. 《新标准C++程序设计》3.5(C++学习笔记8)

    常量对象和常量成员函数 一.常量对象 如果希望某个对象的值初始化后就再也不被改变,则定义该对象时可以在前面加const关键字,使之成为常量对象. class CDemo { private: int ...

  7. 正确处理类的复合关系------新标准c++程序设计

    假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类.狗是有主人的,主人也有狗.假定狗只有一个主人,但一个主人可以有最多10条狗.该如何处理“主人”类和“狗”类的关系呢?下面是 ...

  8. 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计

    类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...

  9. 多态实现的原理------新标准c++程序设计

    “多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespac ...

  10. 多态的作用-游戏编程展示------新标准c++程序设计

    游戏软件的开发最能体现面向对象设计方法的优势.游戏中的人物.道具.建筑物.场景等都是很直观的对象,游戏运行的过程就是这些对象相互作用的过程.每个对象都有自己的属性和方法,不同对象也可能有共同的属性和方 ...

随机推荐

  1. java并发初探ReentrantWriteReadLock

    java并发初探ReentrantWriteReadLock ReenWriteReadLock类的优秀博客 ReentrantReadWriteLock读写锁详解 Java多线程系列--" ...

  2. linux 串口通信 编程详解

    计算机串口的引脚说明 序号 信号名称 符号 流向 功能 3 发送数据 TXD DTE→DCE DTE发送串行数据 2 接收数据 RXD DTE←DCE DTE 接收串行数据 7 请求发送 RTS DT ...

  3. 转:Nginx 性能优化有这篇就够了!

    目录: https://mp.weixin.qq.com/s/YoZDzY4Tmj8HpQkSgnZLvA 1.Nginx运行工作进程数量 Nginx运行工作进程个数一般设置CPU的核心或者核心数x2 ...

  4. Django 3.0中不推荐使用的及已经删除的功能

    3.0中不推荐使用的功能 django.utils.encoding.force_text()和smart_text()的别名被弃用.如果您的代码支持Python 2,smart_str()并且 fo ...

  5. Pycharm 报错 Environment location directory is not empty 解决

    新电脑clone项目后发现Project Interpreter无法配置, New environment 选择后无法应用, 鼠标悬停在Location 提示 Environment location ...

  6. SQL SERVER查询数据库所有的表名/字段

    SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='subject' --表名 1.利用sysobjects系统表 在这个表中,在数据 ...

  7. clientDataSet转换sql

    ReadMe 新版本delphi,可以用string类型,旧版本需要用widestring =========================================== function T ...

  8. CSS-text-intent

    text-indent:[ <length> | <percentage> ] && ? && ? 默认值:0 适用于:块容器 继承性:有 动画 ...

  9. Intellij IDEA中配置TFS

    TFS是微软推出的一款研发过程管理利器,C#阵营的VS里做了默认集成,但是对于Java阵营的Intellij IDEA,需要安装插件并进行相应配置才能使用: 1.打开配置 2.搜索并安装插件 3.配置 ...

  10. 无法识别的配置节 system.webServer

    Web.config文件里面加入 <configSections> <section name="system.webServer" type="Sys ...