类
1,类对象的初始化
构造函数的作用是在创建类的对象时进行类对象初始化的
在 C++ 中,每个类都有且必须有构造函数。如果用户
没有
自行编写构造函数,则 C++
自动提供
一个无参数的构造函数,称为默认构造函数。这个默认构造函数不做任何初始化工作。一旦用户编写了构造函数,则这个
无参数的默认构造函数就消失了
。如果用户还希望能有一个无参数的构造函数,
必须自行编写
。
一、
无参数
的构造函数
#include <iostream>
#include <string>
using namespace std;
class Cstudent
{
public:
Cstudent() //构造函数名要与类名相同
{
name = "zhangsan";
school = "yizhong";
tele = 12345;
} //在构造函数中直接对成员初始化
void set_data();
void show_data();
private:
string name;
string school;
int tele;
};
void Cstudent::set_data()
{
cin >> name;
cin >> school;
cin >> tele;
return;
}
void Cstudent::show_data()
{
cout <<""<< name <<" "<< school<< " " << tele << endl;
return;
}
int main()
{
Cstudent C1;
C1.set_data();
C1.show_data();
//对学生数据进行修改,输出为set_data函数输入的值
Cstudent C2;
C2.show_data();
//C2对象没有调用set_data函数对成员修改,直接输出初始化中的初始值。
return 0;
}
ps:
但是在调用无参数的构造函数创建对象时,
不能加括号!!!
二、带参数的构造函数
区别于第一种类的定义,加入构造函数Cstudent
class Cstudent
{
public:
Cstudent(string, string, int); //类名 (类型1,类型2,类型3)
//类型与初始化数据类型一致
void set_data();
void show_data();
private:
string name;
string school;
int tele;
};
在类外需要对其定义
Cstudent::Cstudent(string string1, string string2, int t)
{
name = string1;
school = string2;
tele = t;
}
在主函数对象定义时为
类名 对象名(实参1,实参2,实参3);
int main()
{
Cstudent C1("wanger","yizhong",2341); //对其进行初始化数据
C1.show_data();
Cstudent C2("Lisi", "yizhong", 12311);
C2.show_data();
return 0;
}
带参数较无参数的
对类、类外函数、main函数
添加修改
即毕
三、带默认参数的构造函数
类的定义:
class Cstudent
{
public:
Cstudent(string a = "zhangsan",
string b = "yihzong",
int c = 12414);
void set_data();
void show_data();
private:
string name;
string school;
int tele;
};
类外定义:
Cstudent::Cstudent(string a, string b, int c)
{
name = a;
school = b;
tele = c;
}
main函数中常规定义对象:
Cstudent s1(
"wanger","yizhong",2341
);
可进行默认初始化,也可以在main中全部初始化或部分初始化。
部分初始化只能按顺序;
例:
Cstudent s1(
"wanger"
);初始化第一个
Cstudent s1(
"wanger","yizhong"
);初始化第一第二个
Cstudent s1(
"yizhong",2341
);error
Cstudent s1(
2341
);error
四、带参数初始化表
类中定义
构造函数结构
类名(类型1 形参1…):成员1(类型1…){}
class Cstudent
{
public:
Cstudent(string string1,string string2,int t):name(string1), school(string2), tele(t){}
void set_data();
void show_data();
private:
string name;
string school;
int tele;
};
int main()
{
Cstudent C1("wanger", "yizhong", 2341);
C1.show_data();
Cstudent C2("Lisi", "yizhong", 12311);
C2.show_data();
return 0;
}
注意: 若形参为数组,组需要在函数体{}中使用strcpy函数对其赋值
Cstudent(string dtring1,char s[10]):name(string1) //构造函数
{strcpy(school,s)} //函数体
注意:
Cstudent
C1(
"wanger"
,
"yizhong"
, 2341);
Cstudent
C1=
Cstudent
(
"wanger"
,
"yizhong"
, 2341);
两者完全等价,都只是调用了有参数的构造函数;
特殊成员变量的初始化
C++类中的
1) const 成员,只能在构造函数初始化列表里定义,不能再类外定义,是属于类的一个对象的常量数据成员,不是属于整个类的
2)static成员,需要在类外定义,不需要加static关键字,方式为:type classname::staticname = ...,是属于整个类的,不是某个类的对象
3)static const, const static成员一样,是整个类共享的常量,属于整个类,可以在类外定义,不能再初始化列表中定义,但是有一种情况:
特别地
只有
静态整形常量(每个词都不能少理解)
才能够在
类中(而不是构造函数中,注意区分)
进行初始化(当然也可以在全局区域初始化:
const int A::csti2=100
),其他都不可以。而
常量
因为
没有赋值操作
,因此
只有
构造函数
列表
中的
初始化
。
不过,
可以在定义的时候直接在后面赋值(不建议使用)
常量有位域是,无法直接在类中赋值,只能在初始化列表中赋值
更好的做法
另外,静态变量的初始化是怎么回事呢?static数据成员必须在
全局范围(可以理解为在类外,这也好理解,因为静态变量为所有类的实例通用,即为全局变量,所以这么声明是理所应当的)
进行初始化,使用int TEST(所属类名)::b(静态变量)的形式,这时不能有static限定符。
当然,
普通的数据成员
也
不能在类内
部
直接初始化。
2.类中的结构体--和类相似
C++相对于C对struct进行了大量扩充,主要区别
struct中默认的访问限定符是public
3.析构函数
析构函数于构造函数相对应,构造函数是对象创建的时候自动调用的,而析构函数就是对象在销毁的时候自动调用的。
特点:
1)构造函数可以有多个来构成重载,但析构函数只能有一个,不能构成重载
2)构造函数可以有参数,但析构函数不能有参数
3)与构造函数相同的是,如果我们没有显式的写出析构函数,那么编译器也会自动的给我们加上一个析构函数,什么都不做;如果我们显式的写了析构函数,那么将会覆盖默认的析构函数
4)
析构函数在对象消亡时即自动被调用。可以定义析构函数在对象消亡前做善后工作。
例如,对象如果在生存期间用 new 运算符动态分配了内存,则在各处写 delete 语句以确保程序的每条执行路径都能释放这片内存是比较麻烦的事情。有了析构函数,只要在析构函数中调用 delete 语句,就能确保对象运行中用 new 运算符分配的空间在对象消亡时被释放。
#include
<iostream>
#include
<string>
using
namespace
std;
class
Cperson
{
public
:
Cperson()
{
pp =
new
int
;
cout
<<
"Beginning"
<<
endl;
}
~Cperson()
{
delete
pp;
cout
<<
"End"
<<
endl;
}
private
:
int
* pp;
};
int
main()
{
Cperson
* op1 (
Cperson
*)malloc(
sizeof
(
Cperson
));
free(op1);
Cperson
* op2 =
new
Cperson
;
delete
op2;
system(
"pause"
);
return
0;
}
输出:
Beginning
End
只有new和delete触发了构造函数和析构函数
4.友元函数
友元的目的 就是让一个函数或者类 访问另一个类中的私有成员
友元的关键字为 friend
1)全局函数做友元
2) 类做友元
#include
<iostream>
#include
<string>
using
namespace
std;
// 类作友元
class
Building
;
class
LaoWang
{
public
:
LaoWang();
void
visit();
//参观函数 访问Building中的属性
Building
* building;
};
// 房屋类
class
Building
{
// 告诉编译器,LaoWang类是Building类的好朋友,可以访问Building类的私有成员
friend
class
LaoWang
;
public
:
Building();
string
m_SittingRoom;
// 客厅
private
:
string
m_BedRoom;
// 卧室
};
// 类外定义成员函数
Building
::Building()
{
m_SittingRoom
=
"客厅"
;
m_BedRoom
=
"卧室"
;
}
LaoWang
::LaoWang()
{
// 创建建筑物对象
building =
new
Building
;
}
void
LaoWang
::visit()
{
cout
<<
"隔壁老王LaoWang类正在访问:"
<<
building->m_SittingRoom
<<
endl;
cout
<<
"隔壁老王LaoWang类正在访问:"
<<
building->m_BedRoom
<<
endl;
}
void
test()
{
LaoWang
lw;
lw.visit();
}
int
main()
{
test();
return
0;
}
隔壁老王LaoWang类正在访问:客厅
隔壁老王LaoWang类正在访问:卧室
3)成员函数做友元
class
Student
;
class
man
{
public
:
void
print(
Student
&
stu
);
int
a;
man(){
a = 1;
}
};
class
Student
{
private
:
static
int
a;
int
b;
public
:
Student()
{
b = 2;
}
friend
void
man
::print(
Student
&
stu
);
};
int
Student
::a = 1;
void
man
::print(
Student
&
stu
)
{
cout
<<
stu
.a +
stu
.b
<<
endl;
}
int
main()
{
Student
stu;
man
x;
x.print(stu);
return
0;
}
输出:3