C++--第9课 - 构造与析构 - 上
第9课 - 构造与析构 - 上
1. 对象的初始化
生活中存在的对象都是被初始化后才上市的,初始状态是对象普遍存在的一个状态的。一般而言所有的对象都需要一个确定的初始状态。
解决方案:
为每个类都提供一个public的initialize函数;对象创建后立即调用initialize函数进行初始化。
#include <stdio.h>
class Test
{
private:
int i;
public:
void initialize()
{
i = 0;
}
int getI()
{
return i;
}
};
int main()
{
Test t1;
Test t2;
Test t3;
t1.initialize();
t2.initialize();
t3.initialize();
printf("t1.i = %d\n", t1.getI());
printf("t2.i = %d\n", t2.getI());
printf("t3.i = %d\n", t3.getI());
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果,各个变量的值都变成了1。
initialize只是一个普通的函数,必须显示的调用。一旦由于失误的原因,对象没有初始化,那么结果将是不确定的。没有初始化的对象,其内部成员变量的值是不定的。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
void initialize()
{
i = 0;
j = 0;
k = 0;
}
void print()
{
printf("i = %d, j = %d, k = %d\n", i, j, k);
}
};
int main()
{
Test t1;
Test t2;
Test t3;
t1.print();
t2.print();
t3.print();
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果,各个变量的值不定。
2. C++中的构造函数
C++中的类可以定义与类名相同的特殊成员函数;这种与类名相同的成员函数叫做构造函数;构造函数在定义时可以有参数,但是没有任何返回类型的声明。
class Test
{
private:
int i;
int j;
int k;
public:
Test(int v)
{
i = j = k =v;
}
......
}
l 构造函数的调用
一般情况下C++编译器会自动调用构造函数,在一些情况下则需要手工调用构造函数。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
Test(int v)
{
i = v;
j = v;
k = v;
}
void print()
{
printf("i = %d, j = %d, k = %d\n", i, j, k);
}
};
int main()
{
Test t1(4); //自动调用构造函数
Test t2 = 5; //自动调用构造函数
Test t3 = Test(6); //主动调用构造函数
t1.print();
t2.print();
t3.print();
Test tA[3] = {Test(1), Test(2), Test(3)}; //主动调用构造函数,不手动写会报错。
for(int i=0; i<3; i++)
{
tA[i].print();
}
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
i = 4, j = 4, k =4
i = 5, j = 5, k =5
i = 6, j = 6, k =6
i = 1, j = 1, k =1
i = 2, j = 2, k =2
i = 3, j = 3, k =3
l 成员函数的重载
类的成员函数和普通函数一样可以进行重载,并遵守相同的重载规则。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
Test()
{
i = 0;
j = 0;
k = 0;
}
Test(int v)
{
i = v;
j = v;
k = v;
}
void print()
{
printf("i = %d, j = %d, k = %d\n", i, j, k);
}
void print(int v)
{
printf("v = %d\n", v);
}
};
int main()
{
Test t1(4);
Test t2 = 5;
Test t3 = Test(6);
Test t4;
t4.print();
t1.print();
t2.print();
t3.print();
Test tA[3];
for(int i=0; i<3; i++)
{
tA[i].print();
}
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
i = 0; j = 0; k = 0
i = 4; j = 4; k = 4
i = 5; j = 5; k = 5
i = 6; j = 6; k = 6
i = 0; j = 0; k = 0
i = 0; j = 0; k = 0
i = 0; j = 0; k = 0
定义数组没有初始化,Test tA[3]使用了没有参数的构造函数。
3. 两个特殊的构造函数
#include <stdio.h>
/*
注意:
1. 当类中没有定义任何一个构造函数,C++编译器会为提供无参构造函数和拷贝构造函数
2. 当类中定义了任意的非拷贝构造函数时,C++编译器不会为提供无参构造函数
*/
class Test
{
public:
Test()
{
printf("Test()\n");
}
Test(const Test& obj)
{
printf("Test(const Test& obj)\n");
}
};
int main()
{
Test t1;
Test t2 = t1;
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
Test<>
Test<const Test& obj>
无参构造函数
当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空。
拷贝构造函数
当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值复制。
#include <stdio.h>
class Test
{
private:
int i;
int j;
int k;
public:
void print()
{
printf("i = %d, j = %d, k = %d\n", i, j, k);
}
};
int main()
{
Test t1;
Test t2 = t1;
t1.print();
t2.print();
printf("Press any key to continue...");
getchar();
return 0;
}
运行结果:
i = 4200582, j = 2686760, k =4200678
i = 4200582, j = 2686760, k =4200678
编译器提供的复制函数,将对应函数一一赋值。
4. 写代码--创建数组类
Array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_
class Array
{
private:
int mLength;
int* mSpace;
public:
Array(int length);
Array(const Array& obj);
int length();
void setData(int index, int value);
int getData(int index);
void destory();
};
#endif
Array.cpp
#include "Array.h"
Array::Array(int length)
{
if( length < 0 )
{
length = 0;
}
mLength = length;
mSpace = new int[mLength];
}
Array::Array(const Array& obj)
{
mLength = obj.mLength;
mSpace = new int[mLength];
for(int i=0; i<mLength; i++)
{
mSpace[i] = obj.mSpace[i];
}
}
int Array::length()
{
return mLength;
}
void Array::setData(int index, int value)
{
mSpace[index] = value;
}
int Array::getData(int index)
{
return mSpace[index];
}
void Array::destory()
{
mLength = -1;
delete[] mSpace;
}
main.c
#include <stdio.h>
#include "Array.h"
int main()
{
Array a1(10);
for(int i=0; i<a1.length(); i++)
{
a1.setData(i, i);
}
for(int i=0; i<a1.length(); i++)
{
printf("Element %d: %d\n", i, a1.getData(i));
}
Array a2 = a1;
for(int i=0; i<a2.length(); i++)
{
printf("Element %d: %d\n", i, a2.getData(i));
}
a1.destory();
a2.destory();
printf("Press any key to continue...");
getchar();
return 0;
}
小结:
构造函数是C++中用于初始化对象状态的特殊函数。
构造函数在对象创建时自动被调用。
构造函数和普通成员函数都遵循重载规则。
拷贝构造函数是对象正确初始化的重要保证。
转载于:https://www.cnblogs.com/free-1122/p/11336187.html
C++--第9课 - 构造与析构 - 上相关推荐
- C++ - 构造和析构 2018-01-10
/*回顾上节的内容:1.实现中的事情 物 ->类 <属性 -> 成员变量> <行为 -> 成员函数>2.访问权限 public private (protec ...
- php构造和析构方法,php5构造函数与析构函数实例
自php5起,有了构造函数与析构函数. 这使得php更富有面向对象的魅力了. 在php4时,构造函数用的是与类同名的函数来进行构造这个动作. 例如: 复制代码 代码示例: /* * myclass.p ...
- 【设计原则和建议】 构造和析构对象
良好的构造和析构对象,控制对象生命周期可以较大的提高程序的性能,降低GC的压力,减少BUG几率. 本文还是比较简单的,主要还是经验的总结,很多东西也许各位已经知道,也许不知道.希望大家一起讨论. 1. ...
- C++系列总结——构造与析构
前言 在使用资源前,我们需要做一些准备工作保证资源能正常使用,在使用完资源后,我们需要做一些扫尾工作保证资源没有泄露,这就是构造与析构了,这和编程语言是无关的,而是使用资源的一种方式.C++只不过是把 ...
- 声明及赋值_重述《Effective C++》二——构造、析构、赋值运算
关于本专栏,请看为什么写这个专栏.如果你想阅读带有条款目录的文章,欢迎访问我的主页. 构造和析构一方面是对象的诞生和终结:另一方面,它们也意味着资源的开辟和归还.这些操作犯错误会导致深远的后果--你需 ...
- c++多个对象构造和析构
多个对象构造和析构 对象初始化列表 对象初始化列表出现原因 注意概念 注意 总结 对象初始化列表 对象初始化列表出现原因 1.必须这样做: 如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个 ...
- (转)剖析Delphi中的构造和析构
剖析Delphi中的构造和析构 1 Delphi中的对象模型: 2 1.1 对象名表示什么? 2 1.2 对象存储在哪里? 2 1.3 对象中存储了什么?它们是如何存储的? 3 2 构造函数与创建对象 ...
- 【No.7 C++对象的构造与析构时间】
==[注意]== 程序语言只是我们与计算机交流并让计算机实现我们创造性思想的工具,可以并鼓励深入掌握一门语言,但千万别沉迷于钻某种语言的牛角尖,一定要把握好二者间的度 本帖属不定时连载贴,以试卷的形式 ...
- 【C++深度剖析教程25】继承中的构造与析构
今天来学习C++中继承的构造与析构,有兴趣一起学习的加qq:1126137994 1.问题 如何初始化父类成员?父类构造函数与子类构造函数有什么关系? 子类对象是如何构造的? 子类中可以定义构造函数 ...
- c/c++入门教程 - 2.4.6 继承、公共继承、保护继承、私有继承、virtual虚继承(概念、语法、方式、构造和析构顺序、同名成员处理、继承同名静态成员处理、多继承语法、菱形继承、钻石继承)
目录 4.6 继承 4.6.1 继承的基本语法 4.6.2 继承方式 4.6.3 继承中的对象模型 4.6.4 继承中构造和析构顺序 4.6.5 继承同名成员处理方式 4.6.6 继承同名静态成员处理 ...
最新文章
- 微服务架构之「 容错隔离 」
- 浪潮集团执行总裁王柏华:这次人工智能产业发展大潮“是真的”
- (视频+图文)机器学习入门系列-第6章 机器学习库Scikit-learn
- js实现svg图形转存为图片下载[转]
- 408考研数据结构复习-时间复杂度与空间复杂度-附统考真题
- SpingBoot+Mybaits+Vue,更新学习
- android studio云测,Android studio 下的robotium自动化测试和持续集成
- Tensorflow学习——导入数据
- springmvc java中转发_springmvc实现转发和重定向
- 控件制作之design-time attribute
- mysql cpu高 重启无效_解决mysqlcpu高的问题
- python课程-天津Python编程课程
- OV5640时钟理解与端口理解(一)
- 怎么制作鸿蒙系统启动盘,dos系统启动盘怎样做
- 工作环境配置及putty工具常见设置
- SQL SERVER提示'Modify' 附近有语法错误
- 客服坐席聊天页面html,WebSocket实现简单客服聊天系统
- C语言C Prime总结(2-7章)
- 一个在图片上写字的方法
- ES5和ES6的类,静态方法,继承实现代码
热门文章
- 进程间通信-----管道
- Android ViewFilpper实现分页效果
- java多个收银台收银_Java策略模式设计(简易收银台SpringBoot)
- Flink State - Backend Improvements and Evolution in 2021
- 异步处理老司机:IntentService 源码分析
- 还在使用OpenGL ES做渲染,你Out了,赶紧来拥抱Vulkan吧~
- linux数组删除数据,如何从shell数组中删除一个元素
- java 动态转换器_非常简单的Java动态转换
- 滴滴android面试算法,滴滴打车面试经验
- eja智能压力变送器工作原理_eja变送器详解_eja变送器工作原理_eja变送器如何选型...