//接口文件strvar.h
#ifndef STRINGVAR_H
#define STRINGVAR_H
#include <iostream>
using namespace std;
namespace sunyufeng
{
class StringVar
{
public:
StringVar(int size);
StringVar();
StringVar(const char a[]);
StringVar(const StringVar& string_object);
~StringVar();
int length() const;
void input_line(istream& ins);
void operator = (const StringVar& right_side);
friend ostream& operator << (ostream& outs,const StringVar& the_string);
private:
char *value;
int max_length;
};//StringVar
}//sunyufeng
#endif
//实现文件 strvar.cpp
#include <iostream>
#include <cstdlib>
#include <cstddef>
#include <cstring>
#include "StringVar.h"
using namespace std;
namespace sunyufeng
{
StringVar::StringVar(int size):max_length(size)
{
value = new char[max_length+1];
value[0] = '/0';
}
StringVar::StringVar():max_length(100)
{
value = new char[max_length+1];
value[0] = '/0';
}
StringVar::StringVar(const char a[]):max_length(strlen(a))
{
value = new char[max_length+1];
strcpy(value,a);
}
StringVar::StringVar(const StringVar& string_object):max_length(string_object.length
())
{
value = new char[max_length+1];
strcpy(value,string_object.value);
}
StringVar::~StringVar()
{
delete [] value;
}
int StringVar::length() const
{
return strlen(value);
}
void StringVar::input_line(istream& ins)
{
ins.getline(value,max_length+1);
}
void StringVar::operator = (const StringVar& right_side)
{
int new_length = strlen(right_side.value );
if (new_length>max_length)
{
delete [] value;
max_length = new_length;
value = new char[max_length+1];
}
for(int i=0;i<new_length;i++)
value[i] = right_side.value [i] ;
value[new_length]='/0';
}
ostream& operator << (ostream& outs,const StringVar& the_string)
{
outs<<the_string.value;
return outs;
}
}//sunyufeng
//应用程序 main.cpp
#include <iostream>
#include "StringVar.h"
void conversation(int max_name_size);
int main()
{
using namespace std;
conversation(30);
cout<<"end of demonstration."<<endl;
return 0;
}
void conversation(int max_name_size)
{
using namespace std;
using namespace sunyufeng;
StringVar your_name(max_name_size),our_name("Borg");
cout<<"What is your name ?"<<endl;
your_name.input_line (cin);
cout<<"we are "<<our_name<<endl;
cout<<"we will meet again "<<your_name<<endl;
}
析构函数是类的一个成员函数,它在类的对象超出作用域之后自动调用。例如,假定类类型的一个对象是
某函数的局部变量,那么调用析构函数就是函数调用结束之前采取的最后一项行动。析构函数用于销毁由
对象创建的任意的动态变量,将这些动态变量占用的内存返还给堆区。析构函数还可以执行其他清理工作
。但将内存收回到堆区才是析构函数的主要工作。
析构函数没有参数,每个类只能有一个析构函数,而且析构函数不能重载。
拷贝构造函数是含有一个传引用调用参数的构造函数,它具有与类相同的类型。这个参数必须是一个传引
用调用参数;通常,参数是一个常量参数。只要某个函数返回类类型的一个值,就会自动调用那个类的拷
贝构造函数。如果类定义涉及到指针以及使用操作符new来动态分配内存,你需要包括一个拷贝构造函数
。不涉及指针或者动态分配内存的类则不需要拷贝构造函数。
Big Three
复制构造函数、=操作符以及析构函数统称为big three。如果你需要定义其中任何一个,就必须定义全
部三个。缺少任何一个,编译器会帮你创建它,只是可能达不到你所预期的效果。所以,你有必要每次定
义他们。假如所有成员变量都具有与定义类型(比如int和double),那么编译器为你生成的拷贝构造函
数和重载操作符=能够很好的工作。然而,假如一个类中包含类或者指针成员变量,它们就有可能表现异
常。对于使用了指针和操作符new的任何类,最保险的做法就是定义你自己的拷贝构造函数、重载操作符=
以及析构函数。
赋值和初始化
C++对初始化和赋值进行了细致的区分。初始化用拷贝构造函数来新建一个对象;赋值操作符获得一个现
有对象,并对其进行修改,使其成为与赋值操作符右侧的对象完全相同的一个副本(准确的说,两者除了
位置不同,其余完全相同)。