静态类成员有一个特点:无论创建了多少对象,程序都只创建一个静态变量副本
在构造函数中使用new来分配内存时,必须在相应的析构函数中使用delete来释放内存。如果使用new[](包括中括号)来分配内存,则应使用delete[](包括中括号)来释放内存。
C++提供了下面这些函数:
复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中(包括按值传递参数),而不是常规的赋值过程。
Class_name(const Class_name&);
它接受一个指向类对象的常量引用作为参数
最常见的情况是将新对象显示转化为现有对象
每当程序生成了对象副本时,编译器都将使用复制构造函数。(当函数按值传递对象或函数返回对象时,都将使用复制构造函数)
默认的复制构造函数逐个复制非静态成员(成员复制也称为浅复制),复制的是成员的值。
StringBad::StringBad(const StringBad& st)
{
num_strings++; //handle static member update
len = st.len; //same length
str = new char[len + 1]; //allot space
std::strcpy(str, st.str); //copy sting to new location
cout << num_strings << ": \"" << str
<< "\" object created\n"; //For Your Information
}
原型如下:
Class_name & Class_name::operator=(const Class_name&);
对于由于默认赋值运算符不合适而导致的问题,解决办法是提供赋值运算符(进行深度复制)定义。
StringBad& StringBad::operator=(const StringBad& st)
{
if (this == &st) //object assigned to itself
return *this;
delete[] str;
len = st.len;
str = new char[len + 1];
std::strcpy(str, st.str);
return *this;
}
赋值操作并不创建新的对象,因此不需要调整静态数据成员num_strings的值。(没有num_strings++)
可以将成员函数声明为静态的(函数声明必须包含关键字static),但如果函数定义时独立的,则其中不能包含关键字static。
不能通过对象调用静态成员函数(静态成员函数甚至不能使用this指针),如果静态成员函数是在公有部分声明的,则可以使用类名和作用域解析运算符来调用它。例如,可以给String类添加一个名为HowMany()的静态成员函数,方法是在类声明中添加如下原型/定义:
static int HowMany() {return num_strings;}
调用它的方式如下:
int count = String::HowMany();
静态成员函数不与特定的对象相关联,因此只能使用静态数据成员。
为提高处理效率,最简单的方法是重载赋值运算符,使之能够直接使用常规字符串,这样就不用创建和删除临时对象了
逐成员复制将使用成员类型定义的复制构造函数和赋值运算符
当成员函数或独立的函数返回对象时,有几种返回方式可供选择。可以返回指向对象的引用、指向对象的const引用或const对象。
返回对象将调用复制构造函数,但返回引用不会。
如果被返回的对象是被调用函数中的局部变量,则不应按引用方式返回它。
返回const对象,能够清楚地指出误用及滥用的方法
总之,如果方法或函数要返回局部对象,则应返回对象,而不是指向对象的引用。在这种情况下,将使用它的复制构造函数来生成对象。如果方法或函数要返回一个没有公有复制构造函数的类(如ostream类)的对象,它必须返回一个指向这种对象的引用。引用效率高。
定位new运算符让您能够在分配内存时能够指定内存位置,要使用不同的内存单元,程序员需要提供两个位于缓冲区的不同地址,并确保两个内存单元不重叠。
delete可与常规new运算符配合使用,但不能与定位new运算符配合使用。
需要显示调用析构函数,必须指定要销毁的对象
pc3->~JustTesting(); // destory object pointed to by pc3
pc1->~JustTesting();
//对于使用定位运算符创建的对象,应以与创建顺序相反的顺序进行删除。
要将单个值转换为类类型时,需要创建原型如下所示的类构造函数:
c_name(type_name value);
其中c_name为类名,type_name是要转换的类型的名称。
要将类转换为其他类型,需要创建原型如下的类成员函数值:
operator type_name(); //应返回所需类型的值
如果使用new运算符来分配类成员指向的内存
className(const className&)
c_name& c_name::operator=(const c_name& cn)
{
if (this == &cn)
return *this;
delete[] c_pointer;
c_pointer = new type_name[size];
...
return *this;
如果Classy是一个类,而mem1、mem2和mem3都是这个类的数据成员,则类构造函数可以使用如下的语法来初始化数据成员:
Classy::Classy(int n, int m) :mem1(n), mem2(0), mem3(n*m + 2)
{
//...
}
上述代码将mem1初始化为n,将mem2初始化为0,将mem3初始化为n*m + 2。从概念上说,这些初始化工作是在对象创建时完成的,此时还未执行括号中的任何代码。