day04 C++构造函数和初始化、对象创建和销毁、类型转换构造函数、拷贝构造函数

本文深入探讨C++中类的定义与实例化过程,包括构造函数、析构函数及成员函数等内容。同时介绍了如何利用构造函数进行对象初始化,并演示了多文件编程实践。此外,还详细讲解了构造函数重载、拷贝构造函数及其调用时机。
回顾:
1 引用型函数返回值
2 引用和指针
3 类型转换
1)隐士转换
2)强制转换、C++四种操作符形式类型转换
 
4 类和对象
======================
十三 类的定义和实例化
1 类的一般形式
class/struct 类名:继承表{
访问控制限定符:
   //构造函数
   类名(形参表)[:初始化表]{函数体}
 
   //析构函数
   ~类名(void){函数体}
 
   //成员函数
   返回类型 函数名(形参表)[const]{//函数体}
 
   //成员变量
   数据类型 变量名;
};
 
2 访问控制限定符
public:公有成员,在类内部和外部都可以访问。
private:私有成员,只能在类的内部访问。
protected:保护成员(后面讲)
 
3 构造函数(Construtors)
class/struct 类名{
   //构造函数
   类名(形参表){函数体}
};
1)构造函数名字和类名相同,没有返回类型
2)构造函数在对象被创建时自动被调用
3)构造函数主要负责对象的初始化,即初始化成员变量
4)构造函数在每个对象的声明周期,一定会被自动调用,  
   但只会被调用一次

 
练习:实现电子时钟类,使用构造函数接收当前系统时间,初始化电子时钟对象,以秒运行。
class Clock{
public:
   Clock(time_t t){
      tm* local = localtime(&t);
      //初始化成员变量:时分秒
      时 = local->tm_hour;
      分 = local->tm_min;
      秒 = local->tm_sec;}
   void run(void){
      死循环{打印时间;计时+1秒;sleep(1)}}
private:
   int m_hour;
   int m_min;
   int m_sec;
};
int main(void){
    Clock c(time(NULL));
    c.run();
    return 0;
}
 
4 多文件编程:类的声明和定义可以放在不同的文件中
1)类的声明放在"xx.h"头文件中
2)类的实现部分放在"xx.cpp"源程序中
 
5 对象的创建和销毁
1)在栈中创建单个对象 //重点掌握
  类名 对象(构造实参表);
  类名 对象 = 类名(构造实参表);//和上面等价
 
  注:如果构造函数没有参数
  类名 对象;
  类名 对象 = 类名();//和上面等价
 
2)在栈中创建对象数组
  类名 对象数组[元素个数] = {类名(构造实参表),...}
 
3)在堆区创建/销毁单个对象 //重点掌握
创建:类名* 对象指针 = new 类名(构造实参表);
销毁:delete 对象指针;
 
4 在堆区创建/销毁多个对象
创建:类名* 对象指针 =  
        new 类名[元素个数]{类名(构造实参表),...}
 
销毁:delete[] 对象指针;
 
 
十四 构造函数和初始化表
1 构造函数重载
  构造函数可以通过参数表的不同形成重载,创建对象时通过构造实参的类型选择匹配,表示不同对象的创建方式。
 
2 缺省构造函数(默认构造函数/无参构造函数)
1)如果一个类没有定义任何构造函数,编译器会提供一个缺省的无参构造函数。
2)对于类中基本类型的成员变量不初始化
3)对类 类型的成员变量(成员子对象),调用相应类的无参构造函数来初始化

 
注:如果一个类定义了构造函数,无论是否有参数,那么编译器都不会再提供缺省的无参构造函数。
 
eg:
class A{
public:
   A(void){
    m_data = 0;
   }
   int m_data;
};
class B{
public:
   int m_data;//基本类型
   A m_a;//A类 类型
};
int main(void){
   B b;//使用B的缺省构造函数创建b对象
   cout << b.m_data << endl;//未初始化的值
   //调用A的无参构造函数初始化m_a(成员子对象)
   cout << b.m_a.m_data << endl;//0
}
 
3 类型转换构造函数(单参构造函数)
class 目标类型{
   [explicit] 目标类型(源类型){...}
};
可以接收单个源类型对象实参的构造函数,支持从源类型到目标类型的隐士转换。
 
explicit关键字:用于修饰类型转换构造函数,强制的要求这种转换必须显示的进行。
 
4 拷贝构造函数(复制构造函数)
4.1 定义
用一个已存在的对象构造同类型的副本对象时,会调用该类的拷贝构造函数:
   类名 (const 类名& that){...}
eg:
class A{
   A(const A& that){...}
};
A a1;
A a2(a1);//调用拷贝构造函数
A a2 = a1;//和上面等价
 
4.2 缺省拷贝构造函数
1)如果一个类没有定义拷贝构造函数,那么编译器会为该类提供一个缺省的拷贝构造函数。
2)对基本类型的成员变量,按字节复制。
3)对类 类型的成员变量(成员子对象),调用相应类拷贝构造函数来初始化。

 
注:如果自己定义了拷贝构造函数,那么编译器将不再提供缺省拷贝构造函数,要实现成员变量复制的操作,必须在自己定义的拷贝构造函数中编写代码完成。
 
 
4.3 拷贝构造函数调用时机:
1)用已经定义的对象作为同类型对象构造实参
2)以对象的形式向函数传递参数
3)从函数中返回对象(有时会被编译器优化掉)

eg:
class A{
   A(const A& that){...}
};
void func(A a3){...}
 
A func2(void){
   A a4;
   return a4;//3)  
}
int main(void){
   A a1;
   A a2(a1);//1)
   func(a1);//2)
   A a5 = func2();//3)
}
 
总结:
自己定义的构造       编译器提供的构造函数
无参构造          缺省拷贝构造
拷贝构造          无
无                缺省拷贝构造、缺省无参构造
 
 
练习:构造函数的使用


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值