版权声明:转载之前请说你是博主的粉丝哦。 https://blog.csdn.net/qq_34921856/article/details/83658301
复制构造函数
- 如果没有定义,编译器将默认提供复制构造函数
- 原型
Class_name(const Class_name &) StringBad(const StringBad &)
- 何时调用
StringBad ditto(motto); StringBad metoo=motto; StringBad also=StringBad(motto); StringBad *pStringBad = new StringBad(motto);
- 有何功能
当类的成员是使用new初始化的,指向数据的指针,而不是数据本身时,我们需要重新定义复制构造函数。
需要注意的是,由于按值传递对象将调用复制构造函数,因此如果有参数列表有值传递的函数时,请改成使用引用传递的函数。
赋值运算符
-
同复制构造函数的功能类似。
-
原型
Class_name & Class_name::operator=(const Class_name &); StringBad & StringBad::operator=(const StringBad &);
-
何时调用
StringBad headline1("Hello World");//复制构造函数 StringBad knot; knot = headline1;//赋值运算符
-
有何功能
- 同复制构造一样,当成员函数含有指针的时候,同样需要手动创建
- 手动创建时需要注意一些事项
- 需要先释放目标对象之前使用new分配的旧数据
- 应尽量避免将对象赋值给本身 – 否则可能会在赋值前释放其旧数据
- 函数返回一个指向调用对象的引用
- 由此可知赋值函数并不创建新的对象
- 可以进一步重载赋值运算符,以支持其他类型到此类的转换
- 如果目前还没有必要实现复制构造和赋值运算符,但也不希望有复制或赋值现象发生,可将这两个函数声明为private且忽略其实现(将永远不会被调用)
中括号运算符重载
-
简单实现
//声明 char & operator[](int i); //定义 char & String::operator[](int i) { return str[i]; }
-
当变量被const修饰时,使用该方法会报错,因为上述方法无法保证不修改数据。故需提供另一个仅供const String对象的operator版本。
const char & String::operator[](int i) { return str[i]; }
静态类成员函数
-
声明必须包括static,定义时不能包含关键字static。
//声明 static int HowMany(); //定义 int String::HowMany() { ...; } //调用 int count = String::HowMany();
-
使用规则
- 不能通过对象调用静态成员函数
- 不能使用this指针
- 如果静态成员函数是在公用部分声明的,则可以使用类名和作用域解析运算符来调用它
类中的new与delete
-
应注意的事项
- 如果构造函数中使用new来初始化指针成员,则应在析构函数中使用delete
- new和delete必须相互兼容,new对应delete,new[]对应于delete[]
- 如果有多个构造函数,则必须以相同的方式使用new。
-
应当定义一个复制构造函数,通过深复制将一个对象初始化为另一个对象
String::String(const String& s) { len = s.len; str = new char[len+1]; // 分配空间 -- 深复制 strcpy(str, s.str); }
-
应当定义一个赋值运算符,通过深度复制将一个对象复制给另一个对象
String& String::operator=(const String& s) { // 返回引用 -- 防止创建额外副本 if(this == &s) return *this; // 自我赋值时 -- 直接返回this delete[] str; // 清理旧数据 len = s.len; str = new char[len+1]; strcpy(str, s.str); return *this; }
有关返回对象的说明
-
返回指向const对象的引用
- 返回对象将调用复制构造函数,而返回引用不会。
- 效率更快。
- 不能返回指向临时变量的引用。
- 参数为const类型的引用的返回值也应该为const类型的引用。
- 返回const引用的函数可以赋值给此类型变量(赋值了一下),也可赋值给const类型的引用,但是不能赋值给非const的引用
const int &Max(const int &a,const int &b) { if(a>b)return a; return b; } int main() { int a=2,b=5; int c=Max(a,b);//隐式转换了一下 const int &d=Max(a,b); c++; cout<<c<<' '<<d<<endl; }
-
返回指向非const对象的引用
- 有时候是为了提高效率 – 如重载赋值运算符
- 也可以返回对象,也可以返回引用 – 返回引用可避免创建新的副本
- 有时候是为了必须这样做 – 如重载
cout的<<
运算符- ostream对象没有公有的复制构造函数
- 有时候是为了提高效率 – 如重载赋值运算符
-
返回对象
- 如果返回的对象是被调用函数中的局部变量,则必须以对象的形式返回。(如重载+运算符)
- 存在复制构造函数创建返回的对象的开销,但无法避免
-
返回const对象
- 主要是为了防止函数(或重载了操作符的表达式)本身成为左值而导致的一些问题
- 如
a+b=k
,如果使用const则会返回错误信息
使用指向对象的指针
- 定位new运算符
-
需显式调用析构函数
-
删除顺序与创建顺序相反
char* buffer = new buffer[maxn]; Point* p1 = new(buffer) Point; Point* p2 = new(buffer + sizeof(Point)) Point(1, 2); p2->~Point(); p3->~Point(); delete[] buffer;
-