关于类和对象的进一步讨论
构造函数与析构函数
对象数组与对象指针
共用数据的保护
对象的动态建立与释放
对象的赋值和复制
静态成员
友元
构造函数
类的数据成员能不能像简单变量一样在声明时初始化? 如 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)
{ }
};
必须使用参数初始化列表对数据成员进行初始化的几种情况
- 数据成员为常量
- 数据成员为引用类型
#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,℞
const float pi;
};
int main(){
A aa(10);
aa.display();
return 0;
}
- 数据成员为没有无参构造函数的类的对象
#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;