一:属性是私有的,若是类外获取,使用get,set方法
使用get set方法
int getHeight(){return height;}
void setHeight(pheight){height = pheight};
二:拷贝构造
1.CFrog.h
#ifndef CFROG_H
#define CFROG_H
//成员变量 属性:height color name
//成员函数 行为:jump eat digist
class Frog
{
public:
Frog();
Frog(int pheight,char pcolor[],char pname[]);
Frog(Frog &frog); //拷贝构造
~Frog();
void jump();
void eat();
void digist();
void setName(char *newName);
private:
int height; //高度
char color[20]; //颜色
char *name; //名字
protected:
};
#endif
2.CFrog.cpp
#include"CFrog.h"
#include<iostream>
using namespace std;
Frog::Frog() //构造函数没有函数类型
{
cout<<"默认构造"<<endl;
height = 5;
strcpy(color,"green");
name = (char *)malloc(20);
memset(name,0,20);
strcpy(name,"guagua");
}
Frog::Frog(int pheight,char pcolor[],char pname[])
{
cout<<"带参构造"<<endl;
height = pheight;
strcpy(color,pcolor);
name = (char *)malloc(20);
memset(name,0,20);
strcpy(name,pname);
}
void Frog::jump()
{
cout<<name<<"jump"<<endl;
}
void Frog::eat()
{
cout<<name<<"eat"<<endl;
digist();
}
void Frog::digist()
{
cout<<"digist"<<endl;
}
//用成员函数去访问成员内部私有变量
//设置名称 重命名
void Frog::setName(char *newName)
{
name = (char *)malloc(20);
memset(name,0,20);
strcpy(name,newName);
}
//拷贝构造函数
Frog::Frog(Frog &frog) //引用与原变量共享一片内存空间
{
height = frog.height;
name = (char *)malloc(20);
memset(name,0,20);
strcpy(name,frog.name);
strcpy(color,frog.color);
cout<<"拷贝构造"<<endl;
}
Frog::~Frog()
{
//释放
free(name);
cout<<"析构函数"<<endl;
}
3.main.c
#include<iostream> //C++输入输出库
using namespace std; //std标准命名空间
#include"CFrog.h"
#include"CBug.h"
#include<conio.h>
#include<ctime>
int main()
{
Frog frog2(10,"gray","hama");
Frog frog3 = frog2; //类对象赋值 执行拷贝构造
frog2.jump();
frog3.jump();
frog3.setName("xiaogongzhu");
frog2.jump(); //对象调用成员函数
frog3.jump(); //对象调用成员函数
return 0;
}
//带参构造
//拷贝构造
//hamajump
//hamajump
//hamajump
//xiaogongzhujump
//析构函数
//析构函数
三:拷贝构造函数知识点
使用一个已经存在的对象来初始化一个新的本类的对象
声明:只有一个参数并且参数为该类对象的引用
如果类中没有说明复制构造函数,则系统自动生成一个缺省复制构造函数,作为该类的公有成员。
类对象赋值,用已经存在的对象生成新的对象--拷贝构造函数
类对象赋值,若是没有写拷贝构造函数,就会走系统默认的拷贝构造函数(只是浅拷贝)
浅复制:将对象数据成员的值进行简单的复制(最好利用系统自动生成的复制构造函数,已完成浅复制
深复制:不仅将对象数据成员的值进行复制,而且对指针型数据成员生成新空间,然后复制对应的值
浅拷贝:若对象成员是指针,(复制地址把值也改变了)会一改全改,需要自己去写一个拷贝构造函数
深拷贝:对指针数据成员开空间,然后复制对应的值
四:触发拷贝构造的3种情况
1.类对象直接赋值 CLabel name = title;
2.类对象作为函数参数时(建立局部对象)
3.函数返回是类对象时(建立临时对象)
五:类对象作为函数参数时,值传递。执行系统默认的拷贝构造(1次)
void copy(CLabel lab); //类对象作为函数参数
void CLabel::copy(CLabel lab) //按值传递 对象赋值 执行系统copy构造
{
strcpy(content,lab.content); //形参的生命周期 调用创建走拷贝构造 用完释放析构
}
空间利用频繁,开销比较大
六:函数返回是类对象时,类对象也是函数参数。执行系统默认的拷贝构造(2次)
CLabel copy(CLabel lab); //函数返回是类对象
CLabel CLabel::copy(CLabel lab)//类对象作为函数参数 执行系统copy构造
{
strcpy(content,lab.content);
return lab;//函数返回是类对象
}
七:什么时候需要自己写拷贝构造
答:类对象中有指针数据成员的时候才需要自己写拷贝构造。
八:函数传参
1.按值传递(值传参消耗的空间特别大)
2.按地址传递(形参是指针)
3.按引用传参,共享一片内存空间。系统开销小,比较推荐。
九:引用传参
类对象引用作为函数参数
void copy(CLabel &lab); //引用传参
void CLabel::copy(CLabel &lab) //引用传参
{
strcpy(content,lab.content); //共用一片内存空间
}
类对象引用作为函数返回
CLabel& copy(CLabel lab); //类对象引用作为函数返回
CLabel& CLabel::copy(CLabel lab) //类对象引用作为函数返回
{
strcpy(content,lab.content); //共用一片内存空间
return lab;
}
小结:共享对象同一片内存空间不需要创建临时变量(不走拷贝构造 析构)系统开销小 比较推荐。
十:转换构造函数
转换构造(存在隐式转换的风险) 用explicit关键字解决
转换构造函数 (一个参数)
类 结构体 都是数据类型 很int 一样 数据类型。类是C++才有的。
错误:
CLabel pwd =20; (转换构造函数) 把20变成CLabel类型(数据类型)(类)
//隐式转换 编译链接却没有问题值得注意(用关键字explicit解决)
正确:
声明写上 explicit CLabel(int x); //转换构造 编译链接就会报错
应该CLabel pwd(20); 编译链接就没有问题了。
十一:构造函数
1.默认构造:无参
2.普通构造:2参及以上
3.转换构造:1参 关键字explicit
4.拷贝构造又叫复制构造
十二:深拷贝和浅拷贝
深拷贝:自己写拷贝构造函数,为指针数据成员开空间再复制
浅拷贝:系统默认的拷贝构造函数是浅拷贝,复制地址,会一改全改
十三:析构
系统分配的空间会自动回收。
程序员手动开空间,就需要手动释放。
malloc需要free
new需要delete
构造就需要析构
析构函数没有参数,因此析构函数不能被重载。