第六章 类与对象(2)

关于类和对象的进一步讨论
构造函数与析构函数
对象数组与对象指针
共用数据的保护
对象的动态建立与释放
对象的赋值和复制
静态成员
友元

构造函数

类的数据成员能不能像简单变量一样在声明时初始化? 如 class Time

{ 
int hour=0;
int minute=0;
int sec=0;    //不可以直接赋值
}

使用构造函数

构造函数的作用是在对象被创建时使用特定的值构造对
象,即把对象初始化为一个特定的状态。
 构造函数是一种特殊的成员函数,它不需用户调用,而是在
对象创建时由系统自动调用。  如果程序中未声明,则系统自动产生一个默认形式的构
造函数,用于创建对象,默认构造函数形式:
类名::类名(){}
默认构造函数是一个空函数
允许为内联函数、重载函数、带默认形参值的
函数
 特殊性质:
 函数名与类名相同
 没有返回值
 声明为公有函数public

为类Date建立构造函数

#include <iostream>
using namespace std;
class Date {
public:
Date(); // 无参构造函数
void setDate(int y,int m,int d);
void showDate();
private:
int year, month, day; };
Date::Date() // 构造函数的实现           函数!!!
{ year=0; month=0; day=0; }
void Date::setDate(int y,int m,int d)
{ year=y; month=m; day=d; }
void Date::showDate()
{ cout<<year<<"."<<month<<"."<<day<<endl; }
int main()
{
Date a_date; 
a_date.showDate();
a_date.setDate(2014,3,25);
a_date.showDate();
return 0;
}
#include <iostream>
using namespace std;
class Date {
public:
Date(int y,int m,int d); // 构造函数
void setDate(int y,int m,int d);
void showDate();
private:
int year, month, day; };
Date::Date(int y,int m,int d) // 构造函数的实现,这里有参数
{ year=y; month=m; day=d; }/*在建立对象时必须给出初始值,如果如此:
                       	    Date a_date; 则会出错
        					如何使Date a_date;不出错?
							Ans:函数的重载*/下面解释
void Date::setDate(int y,int m,int d)
{ year=y; month=m; day=d; }
void Date::showDate()
{ cout<<year<<"."<<month<<"."<<day<<endl; }
int main()
{
Date a_date(2014,3,25); 
a_date.showDate();
return 0;
}
#include <iostream>
using namespace std;
class Date {
public:
Date(); // 无参构造函数1
Date(int y,int m,int d); // 构造函数2
void setDate(int y,int m,int d);
void showDate();
private:
int year, month, day; };
Date::Date() //无参构造函数的实现
{ year=0; month=0; day=0; }
Date::Date(int y,int m,int d) // 构造函数的实现
{ year=y; month=m; day=d; }
void Date::setDate(int y,int m,int d)
{ year=y; month=m; day=d; }
void Date::showDate()
{ cout<<year<<"."<<month<<"."<<day<<endl; }
int main()
{
Date a_date(2014,3,25);//因为函数的重载,在建立对象时给 出或不给出初始值都可以。若输入不是定义时候的的类型报错 如2011.0\jj\main.cpp||In function `int main()':|
\jj\main.cpp|21|warning: passing `double' for converting 1 of `Date::Date(int, int, int)'|
||=== 已完成构建: 0 个错误, 1 个警告 ===|

Date b_date; 
a_date.showDate();
b_date.showDate();
return 0;
}

可以合并成带默认形参值的构造函数:

Date(int y=0,int m=0,int d=0) 
{ year=y; month=m; day=d; }
#include <iostream>
using namespace std;
class Date {
public:
Date(int y=0,int m=0,int d=0)
{ year=y; month=m; day=d; }
void setDate(int y,int m,int d);
void showDate();
private:
int year, month, day; };
void Date::setDate(int y,int m,int d)
{ year=y; month=m; day=d; }
void Date::showDate()
{ cout<<year<<"."<<month<<"."<<day<<endl; }
int main()
{
Date a_date(2001,1);//因为函数的重载,在建立对象时给 出或不给出初始值都可以。这里可以少用参数没输入的系统默认是0  少参数从后往前少 不能日子写了 年月不写 也不能月不写 日年写了
Date b_date;
a_date.showDate();
b_date.showDate();
return 0;
}

在一个类中可以定义多个构造函数,以便对类对象提供不同
的初始化方法。
 多个构造函数使用相同的名字,只是参数的个数或参数的类
型不同,这就是构造函数的重载。
 尽管在一个类中可以包含多个构造函数,但对于每一个对象
来说,建立对象时只执行其中一个构造函数。
 系统根据定义对象时给出的实参形式,决定调用相应的构造
函数.

对象名 +.+函数名是显示调用
构造函数不这么调用(系统自动调用)

利用构造函数创建对象有以下两种方法

: (1) 利用构造函数直接创建对象.其一般形式为:
类名 对象名[(实参表)];
这里的“类名”与构造函数名相同,“实参表”是为构造函数
提供的实际参数
(2)利用构造函数创建对象时,通过指针和new运算符动态建立
对象,用 delete运算符撤销对象。其一般语法形式为:
类名 *指针变量 = new 类名[(实参表)];
new 运算符动态分配内存后,返回指向新对象的指针,需要定
义一个指向该类对象的指针变量存放新对象指针,以便对其
访问。
例如:

Date *d1=new Date(1998,4,28); //创建对象(*date1)
(*d1). setDate(2020,3,10); 
d1->setDate(2020,3,10);
Box *pt;  //没有对象只有指向对象的指针
pt=new Box; pt=new Box(12,13,14); //调用构造函数初始化
delete pt;
void main()
{
Date *date1;
date1=new Date(1998,4,28);//这行date1不可以加*了
// 以上两条语句可合写成:
// Date *date1=new Date(1998,4,28);
cout<<"Date1 output1:"<<endl;
date1->showDate();
date1->setDate(2002,11,14);
cout<<"Date1 output2:"<<endl;
date1->showDate();
delete date1; }

构造函数的初始化列表

——数据成员的初始化
构造函数初始化成员有两种方法
A.使用构造函数的函数体进行初始化

class Date
{
int d, m, y;
public:
Date(int dd, int mm, int yy) {
d=dd;
m=mm;
y=yy; }
Date(int dd, int mm)
{
d=dd;
m=mm;
} 
}

B.使用构造函数的初始化列表进行初始化

格式: 
funname(参数列表):初始化列表//funname是类的名字
{ 函数体,可以是空函数体 } 
其中,初始化列表的形式:
成员名1(形参名1),成员名2(形参名2),成员名n(形参名n)
class Date
{
int d, m, y;
public:
Date(int dd, int mm, int yy)d(dd),m(mm),y(yy)
{ }
Date(int dd, int mm) : d(dd),m(mm)
{ }
};

必须使用参数初始化列表对数据成员进行初始化的几种情况

  1. 数据成员为常量
  2. 数据成员为引用类型
#include <iostream>
using namespace std;
class A{
public:
A(int i):x(i),rx(x),pi(3.14) { }
void display()
{cout<<"x="<<x<<"rx="<<rx<<"pi="<<pi<<endl;}
private:
int x,&rx;
const float pi;
};
int main(){
A aa(10);
aa.display();
return 0;
}
  1. 数据成员为没有无参构造函数的类的对象
#include<iostream>
using namespace std ;
class A //没有无参构造函数的类 { public : A ( int x ) : a ( x ) { }
int a ; } ;
class B { public :
B( int x, int y ) : aa( x ), b( y ) { }
void out()
{ cout << "aa = " << aa.a << endl << "b = " << b << endl ; }
private :
int b ; A aa ; //数据成员aa为没有无参构造函数的类A的对象,a都带参数
} ;
int main ()
{ B objB ( 3, 5 ) ;
objB . out ( ) ;
 }

类成员的初始化的顺序:

按照数据成员在类中的声明顺序(private中)进行初始化,与初始化
成员列表中出现的顺序无关
在这里插入图片描述
先给m_x赋值,现在m_y没有被赋值所以,是个随机数给了m_x,然后x再给m_y;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jdicat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值