C++系列 --- 成员函数、对象拷贝、私有成员
一、综述
类是我们自己定义的数据类型(新类型)
设计类时要考虑的角度:
(1)站在设计和实现者的角度来考虑
(2)站在使用者的角度来考虑
(3)父类,子类
二、类基础
(1)一个类就是一个用户自己定义的数据类型,把类可以想象为一个命名空间,包着一堆东西(成员函数,成员变量)。
(2)一个类的构成:成员变量,成员函数(有许多特殊的成员函数)。
(3)我们访问类成员时,我们就用对象名.成员名来访问成员
如果是指向对象的指针,我们就用指针名->成员名来访问成员。
class student
{
int number;
char name[100];
}
student someone; // 定义类的对象
someone.number = 1000;
student *someone1 = &someone;
someone->number = 1005;
cout << someone1->number << endl;
(4)public成员提供类的接口,暴露给外接,供外界调用;private成员提供各种实现类的细节方法,但不暴露给使用者,外界无法访问这些成员。
(5)struct是成员默认为public的class; struct A{….}
(5)class是成员默认为private(私有)class A{….}
三、成员函数
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。
class Time
{
public:
int Hour; // 小时
int Minute; // 分钟
int Second; // 秒钟
void initTime(int tmpHour, int tmpMinute ,int tmpSecond)
{
Hour = tmpHour;
Minute = tmpMinute;
Second = tmpSecond;
}
}
int main()
{
Time MyTime; // 类对象
MyTime .initTime(MyTime,11,14,5);
cout << MyTime.Hour << endl;
cout << MyTime.Minute << endl;
cout << MyTime.Second << endl;
return 0;
}
当做工程来写
//time.h
#ifndef __MYTIME__
#define __MYTINE__
class Time
{
public:
int Hour; // 小时
int Minute; // 分钟
int Second; // 秒钟
void initTime(int tmpHour, int tmpMinute ,int tmpSecond);
}
#endif
//time.cpp
#include “Tiem.h”
// 成员函数的实现
// 其中::称为作用于运算符,表示initTime这个函数属于Time类
void Time::initTime(int tmpHour,
int tmpMinute ,int tmpSecond)
{
Hour = tmpHour; // 成员函数中可以直接使用成员变量名
Minute = tmpMinute;
Second = tmpSecond;
}
入口函数文件
#include “Time.h”
int main()
{
Time MyTime; // 类对象
MyTime .initTime(MyTime,11,14,5);
cout << MyTime.Hour << endl;
cout << MyTime.Minute << endl;
cout << MyTime.Second << endl;
return 0;
}
四、对象的拷贝
深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错。
对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。
#include <iostream>
using namespace std;
class Student
{
private:
int num;
char *name;
public:
Student();
~Student();
};
Student::Student()
{
name = new char(20);
cout << "Student" << endl;
}
Student::~Student()
{
cout << "~Student " << (int)name << endl;
delete name;
name = NULL;
}
int main()
{
{// 花括号让s1和s2变成局部对象,方便测试
Student s1;
Student s2(s1);// 复制对象
}
system("pause");
return 0;
}
运行结果
执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,这会导致什么问题呢?name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会导致崩溃!
运行结果这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。
拷贝所以,在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。
添加了自己定义拷贝构造函数的例子:
#include <iostream>
using namespace std;
class Student
{
private:
int num;
char *name;
public:
Student();
~Student();
//拷贝构造函数,const防止对象被改变
Student(const Student &s);
};
Student::Student()
{
name = new char(20);
cout << "Student" << endl;
}
Student::~Student()
{
cout << "~Student " <<
(int)name << endl;
delete name;
name = NULL;
}
Student::Student(const Student &s)
{
name = new char(20);
memcpy(name, s.name,
strlen(s.name));
cout << "copy Student"
<< endl;
}
int main()
{
{// 花括号让s1和s2变成局部对象,方便测试
Student s1;
Student s2(s1);// 复制对象
}
system("pause");
return 0;
}
结果
执行结果:调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。
总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
当对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情形:
1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;
2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。
3.浅拷贝带来问题的本质在于析构函数释放多次堆内存,使用std::shared_ptr,可以完美解决这个问题。
五、私有成员
在C++中,为了防止某些数据成员或成员函数从外部被直接访问,可以将它们声明为private,这样编译器会阻止任何来自外部非友元的直接访问。
class Time
{
private:
int Millsecond; // 毫秒
public:
int Hour; // 小时
int Minute; // 分钟
int Second; // 秒钟
void initTime(int tmpHour,
int tmpMinute ,int tmpSecond)
{
Hour = tmpHour;
Minute = tmpMinute;
Second = tmpSecond;
}
void initMillTime(int mls)
{
// 成员函数可以访问成员变量,不管成员是否私有
Millsecond = mls;
}
}
Time myTime;
// 出错,无法访问
//myTime. Millsecond = 1000;
// 私有成员变量的值可以通过公有的成员变量来获取与设置
myTime.initMillTime(1000);
好了,今天的C++学到这里就结束了,喜欢的朋友可以给我点个赞哦!!!