复制构造函数
它接受一个指向类对象的常量引用作为参数,例如
StringBad(const StringBad &);
何时调用
:新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。
假设motto是一个StringBad对象,则下面4种声明都将调用复制构造函数
StringBad ditto(motto);
StringBad metoo = motto;
StringBad also = StringBad(motto);
StringBad * pStringBad = new StringBad(motto);
当函数按值传递对象或函数返还对象时,都将使用复制构造函数。(按值传递意味着创建原始变量的一个副本,编译器生成临时对象时,也将使用复制构造函数)
默认的复制构造函数的功能
默认的复制构造函数逐个复制非静态成员的值
定义一个显式复制构造函数以解决问题
StringBad::StringBad(const StringBad & st)
{
num_strings++;
len = st.len;
str = new char[len + 1];
std::strcpy(str,st.str);
cot << num_strings;
}
必须定义复制构造函数的原因在于,一些类成员是使用new初始化的,指向数据的指针,而不是数据本身。
解决赋值的问题
StringBad & StringBad::operator=(const StringBad & st)
{
if(this == &st)
return *this;
delete [] str;
len = st.len;
str = new char [len + 1];
std::strcpy(str,st.str);
return *this;
}
比较成员函数
bool operator<(const String &st1 , const String &str2)
{
if(std::strcmp(str1.str,str2.str)<0)
return true;
else
return false;
}
bool operator>(const String &str1 , const String &str2)
{
return str2 < str1;
}
bool operator==(const String &str1 , const String &str2)
{
return (std::strcmp(str1.str,str2.str) == 0);
}
使用中括号访问字符
char & String::operator[](int i)
{
return str[i];
}
const ```` const
{
...
}
静态类成员函数
static int Howmany() { return num_strings;}
静态类成员函数不与特定的对象相关联,因此只能使用静态数据成员。
在构造函数中使用new的注意事项
(1)构造函数使用new,则析构函数使用delete
(2)new对应delete,new[]对应delete[]
(3)如果有多个构造函数,构造函数不能既有new又有new[]因为析构函数只有一个
(4)应定义一个复制构造函数,通过深度复制将一个对象初始化为另一个对象,通常与下面相似
String::String(const String & st)
{
num_strings++;
len = st.len;
str = new char [len + 1];
std::strcpy(str,st.str);
}
(5)应当定义一个赋值运算符,通过深度复制将一个对象复制给另一个对象,与下面类似
String & String::operator=(const String & st)
{
if(this = &st)
return *this;
delete[] str;
len = st.len;
str = new char [len + 1];
std::strcpy(str,st.str);
return *this;
}
再谈定位new运算符
char * buffer = new char[BUF];
pc1 = new(buffrer) JustTesting;
pc2 = new JustTesting("Heap1",20);
pc3 = new (buffer) JustTesting("Bad Idea",6);
可以delete pc2但不能delete pc1/pc3因为delete可与常规new运算符配合使用但不能与定位运算符配合使用。
队列类
class Queue
{
private:
struct Node{Item item;struct Node * next;};
enum{Q_SIZE = 10};
Node * front;
Node * rear;
int items;
const int qisze;
..
public:
..
}
qsize初始化不能如同普通变量一样,只能初始化不能赋值。
Queue::Queue(int qs) : qsize(qs)
{
front = rear = NULL;
items = 0;
}
Queue:Queue(int qs) : qszie(qs) , front(NULL) , rear(NULL) , items(0)
{}
对于const类成员和被声明为引用的类成员必须使用这种语法
class Agency{}
class Agent
{
private:
Agency & belong;
..
};
Agent::Agent(Agency & a) : belong(a){...}
入队方法
bool Queue::enqueue(const Item & item)
{
if(isfull())
return false;
Nod * add = new Node;
add->item = item;
add->next = NULL;
items++;
if(front == NULL)
front = add;
else
rear->next = add;
rear = add;
return true;
}
出列方法
bool Queue::dequeue(Item & item)
{
if (front == NULL)
return false;
item = front->item;
items--;
Node * temp = front;
front = front->next;
delete temp;
if(items == 0)
rear = NULL;
return true;
}
析构函数
Queue::~Queue()
{
Node * temp;
while(front != NULL)
{
temp = front;
front = front->next;
delete temp;
}
}