《新标准C++程序设计》3.3-3.4(C++学习笔记7)
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)的更多相关文章
- 《新标准C++程序设计》4.5(C++学习笔记15)
实例:长度可变的整型数组类 int main() { //要编写可变长整型数组类,使之能如下使用: CArray a; //开始里的数组是空的 ; i < ; ++i) a.push_back( ...
- 《新标准C++程序设计》4.6(C++学习笔记16)
重载流插入运算符和流提取运算符 流插入运算符:“<<” 流提取运算符:“>>” cout 是在 iostream 中定义的,ostream 类的对象. “<<” 能 ...
- 《新标准C++程序设计》4.4(C++学习笔记14)
运算符重载为友元函数 一般情况下,将运算符重载为类的成员函数,是较好的选择. 但有时,重载为成员函数不能满足使用要求,重载为普通函数,又不能访问类的私有成员,所以需要将运算符重载为友元. class ...
- 《新标准C++程序设计》4.1(C++学习笔记12)
运算符重载的概念和原理 一.运算符重载的需求 C++预定义的“+.-. * ./.%. ^ .&.~.!.|. = .<< >>.!= ”等运算符,只能用于基本数据类型 ...
- 《新标准C++程序设计》3.8(C++学习笔记10)
友元 友元分为友元函数和友元类两种. 一.友元函数 在定义一个类的时候,可以把一些函数(包括全局函数和其它类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对 ...
- 《新标准C++程序设计》3.5(C++学习笔记8)
常量对象和常量成员函数 一.常量对象 如果希望某个对象的值初始化后就再也不被改变,则定义该对象时可以在前面加const关键字,使之成为常量对象. class CDemo { private: int ...
- 正确处理类的复合关系------新标准c++程序设计
假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类.狗是有主人的,主人也有狗.假定狗只有一个主人,但一个主人可以有最多10条狗.该如何处理“主人”类和“狗”类的关系呢?下面是 ...
- 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计
类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...
- 多态实现的原理------新标准c++程序设计
“多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespac ...
- 多态的作用-游戏编程展示------新标准c++程序设计
游戏软件的开发最能体现面向对象设计方法的优势.游戏中的人物.道具.建筑物.场景等都是很直观的对象,游戏运行的过程就是这些对象相互作用的过程.每个对象都有自己的属性和方法,不同对象也可能有共同的属性和方 ...
随机推荐
- java实现邮箱发送邮件
第一步:封装发件人账号密码 import javax.mail.Authenticator;import javax.mail.PasswordAuthentication; /** * 发件人账号密 ...
- 学习:Android框架
引言 通过前面两篇: Android 开发之旅:环境搭建及HelloWorld Android 开发之旅:HelloWorld项目的目录结构 我 们对android有了个大致的了解,知道如何搭建a ...
- python 中的 *args 和 **kwargs
在阅读Python代码时,经常会看到如下函数的定义: def fun(*args, **kwargs): 很多同学可能会对此感到困惑,这个 * args和 **kwargs是什么东西.为啥会在源码中应 ...
- S7-300 与TP900 组态 棒图 量表 滚动条 滚动条设置的值通过IO输出域显示出来
切换编程语言 注意 一定要 先选中 某一个组织块 例如 OB1 然后单击 菜单 编辑 切换编程语言 组态 300 PLC 的CPU 点击 SIMENSE LOGO 查看 循环 中断 OB35 可以 在 ...
- 关于C/C++的各种优化
一.常量 声明常量可以方便代码的修改,提高复用性. ; +; ; 同时,声明常量也可以减少重复运算,提高代码速度,例子如下: string s; cin>>s; ;i<len;i++ ...
- Net Core3.1 添加 Swagger
一.为什么使用Swagger 随着互联网技术的发展,现在的网站架构基本都由原来的后端渲染,变成了:前端渲染.后端分离的形态,而且前端技术和后端技术在各自的道路上越走越远. 前端和后端的唯一联系,变成了 ...
- 【LeetCode】113. 路径总和 II
题目 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例: 给定如下二叉树,以及目标和 sum = 22, 5 / \ ...
- install正常,deploy上传jar失败致使打包失败
[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------- ...
- f_lseek
我在STM32中移植了fatfs文件系统,实现在SD卡对文件的读写.在普通读写中都没有问题,但是一旦我关闭文件系统,再次打开读写,之前写的数据就被覆盖.比如举个例子: u8 tx_buff ...
- nuxt.js 初始化 npm run dev 报错
在初始化 npm install 了基本依赖后: npm run dev 报错: error in ./server/index.js Module build failed: Error: Plug ...