class CGoods
{
//行为,成员方法
public:
CGoods(char *name = NULL, int amount = 0, double price = 0.0) //构造函数
{
if (name == NULL)
{
mpName = new char[1];
*mpName = '\0';
}
else
{
mpName = new char[strlen(name) + 1];
strcpy(mpName, name);
}
mAmount = amount;
mPrice = price;
}
~CGoods() //析构函数
{
delete[]mpName;
mpName = NULL;
}
CGoods(const CGoods &src) //拷贝构造函数
{
mpName = new char[strlen(src.mpName) + 1];
strcpy(mpName, src.mpName);
mAmount = src.mAmount;
mPrice = src.mPrice;
}
void operator=(const CGoods &src) //赋值函数
{
if (this == &src)
return;
delete[]mpName;
mpName = NULL;
mpName = new char[strlen(src.mpName) + 1];
strcpy(mpName, src.mpName);
mAmount = src.mAmount;
mPrice = src.mPrice;
}
private:
char *mpName;
int mAmount;
double mPrice;
};
没有返回值、函数名字和类名称必须一样
构造函数可以带参数,因此构造函数可以重载
当没有提供任何构造函数的时候,编译器会给类提供默认的构造函数,函数什么也不做,是个空函数
没有返回值 不能带参数 不能重载
拷贝构造函数不能按值传递!!!
把形参复制到实参会调用拷贝构造函数。如果允许拷贝构造函数传值,就会在拷贝构造函数内调用拷贝构造函数,形成永无休止的递归调用从而导致栈满溢出。只能将构造函数修改为A(const A&other),即把传值参数改为常量引用(传指针也不可以,只能改为引用)
用对象初始化对象,默认做的拷贝方式是,按内存字节拷贝过去,俗称浅拷贝!
如果对象占用了外部的资源,那么默认的浅拷贝一定会发生问题的!所以,当默认的浅拷贝发生问题的时候,需要用户自己提供相应的拷贝构造函数
如果对象默认的浅拷贝发生问题,那么有哪些解决方案?
1。提供自定义的拷贝构造函数和赋值运算符的重载函数
2。把拷贝构造函数和赋值运算符的重载函数的声明提供在private里面
赋值步骤:
1,先排除自赋值;2,释放原来的资源;3,重新开辟空间,赋值
OOP的循环队列构造,析构,拷贝构造,赋值函数
class CQueue
{
public:
CQueue(int size = 10) //构造函数
{
mFront = mRear = 0;
mSize = size;
mpQueue = new int[mSize];
}
CQueue(const CQueue &src) //拷贝构造函数
{
cout << "CQueue(const CQueue &src)" << endl;
mFront = src.mFront;
mRear = src.mRear;
mSize = src.mSize;
mpQueue = new int[mSize];
for (int i = mFront; i != mRear; i = (i + 1) % mSize)
{
mpQueue[i] = src.mpQueue[i];
}
}
void operator=(const CQueue &src) //赋值函数
{
cout << "operator=" << endl;
// 先排除自赋值
if (this == &src)
{
return;
}
//释放原来的资源
delete []mpQueue;
mpQueue = NULL;
//重新开辟空间,赋值
mFront = src.mFront;
mRear = src.mRear;
mSize = src.mSize;
mpQueue = new int[mSize];
for (int i = mFront; i != mRear; i = (i + 1) % mSize)
{
mpQueue[i] = src.mpQueue[i];
}
}
~CQueue() //析构函数
{
delete[]mpQueue;
mpQueue = NULL;
}
/*CQueue queue1 ; //queue1被初始化为queue,queue1析构后地址被释放,queue指向变为野指针*/
/*对于对象的运算 =》 左边对象调用成员方法,把右边的对象当做参数传入
queue2.operator=(queue1);
void operator=(const CQueue &src) */
1.对象的生成分两步
a.给对象分配内存 b.调用构造函数构造对象 =》 对象产生了!!!
2.如果没有提供任何构造函数,编译器会产生默认构造函数,空函数;但是如果用户提供
了任意构造函数,编译器就不再产生默认构造函数了!
3.在调用默认构造函数的时候,不要添加()
4.栈上的对象,先构造,后析构;后构造,先析构
5.栈上的对象,定义的时候调用相应的构造函数;return处,要析构栈上的所有对象
class String
{
public:
String(const char*str = NULL) //普通构造函数
{
if (str == NULL)
{
m_data = new char[1];
*m_data = 0;
}
else
{
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
}
String(const String&other) //拷贝构造函数
{
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data,other.m_data);
}
~String() //析构函数
{
delete[]m_data;
m_data = NULL;
}
String &operator = (const String &other) //赋值函数
{
if (this == &other)
{
return *this;
}
delete[]&m_data;
m_data = NULL;
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
}
private:
char*m_data;
};
int *p = new int; //分配int整形大小的空间
int *p = new int();//分配int整形大小的空间并初始化0
int *p = new int(10);//分配int整形大小的空间并初始化10
int *p = new int[10]; 只开辟内存,10个大小为int整形的空间,不进行初始化
int *p = new int[10](); 不仅仅开辟内存,而且还初始化,int,数组所有元素的初值为0
用临时对象,拷贝构造新对象,此时临时对象就被C++编译器优化掉了
对象使用的三个优化规则:
1.函数参数传递对象,用引用传递,不要按值传递
2.如果你的函数返回的是对象的值,请返回一个临时对象,不要返回一个
已经存在的对象
3.接收返回对象的函数,以初始化方式接收,不要用赋值方式接收