头文件 DString.h如下

#ifndef __DSTRING_H
#define __DSTRING_H
#endif #include <stddef.h> class DString
{
public:
DString(const char * c = NULL); // default constructor
DString(const DString &str); // copy constructor - implement DEEP copy ~DString(); /*
必须使用成员函数重载的运算符 = ( ) [ ] ->
必须使用友元函数重载的运算符 << >>
P.S. 一目运算符,建议使用成员函数;二目运算符,建议只用友元函数
*/
DString& operator = (const DString &str);
friend DString operator + (const DString &s1, const DString &s2);
char* dcopy(char * dst, const char * src); private:
char * m_data;
};

实现如下DString.cpp

#include <string.h>

#include "DString.h"

DString::DString(const char * c)
{
if(NULL == c)
{
m_data = new char('\0');
}
else
{
m_data=new char[strlen(c) + ];
dcopy(m_data, c);
}
} DString::DString(const DString &str)
{
if(NULL== str.m_data)
{
m_data=NULL;
}
else
{
m_data=new char[strlen(str.m_data) + ];
dcopy(m_data, str.m_data);
}
} DString::~DString()
{
delete [] m_data;
} DString& DString::operator = (const DString &str)
{
if(this == &str) // the same one
{
return *this;
}
else
{
delete [] m_data;
m_data=new char[strlen(str.m_data)+];
dcopy(m_data,str.m_data);
return *this;
}
} // no :: because friend function doesnt belong to the class
DString operator + (const DString &s1, const DString &s2)
{
if(NULL == s1.m_data)
{
return DString(s2);
} if(NULL == s2.m_data)
{
return DString(s1);
} char * temp = new char[strlen(s1.m_data) + strlen(s2.m_data) + ];
strcpy(temp, s1.m_data);
strcpy(temp+strlen(s1.m_data), s2.m_data); return DString(temp);
} char* DString::dcopy(char * dst, const char * src)
{
char * tmp = dst; while(*src != '\0')
{
*tmp++ = *src++;
} *tmp = ; return dst;
}

DString.cpp

调用入口main.cpp

#include "DString.h"

int main(int argc, char* argv[])
{
DString s1("abcde"); //call default cons
DString s2 = "ABC"; //call default cons DString s3 = s2; //call copy cons
DString s4(s3); //call copy cons s1 = s4; //call operator = s4 = s1 + s2 + "ding"; //call default cons then + then + then =
return ;
}

一些知识点(以在代码中出现的顺序排列)

  1. 对于一个空的类,默认会有6个成员函数:构造/析构/拷贝构造/赋值/const取址/非const取址
  2. 在函数声明时使用了默认参数,则在实现时就不能再次指定默认参数
  3. 对于基本类型(没有析构函数)释放内存时delete同delete[] (原则是与NEW NEW[]配对使用)
  4. 显示声明拷贝构造函数以实现深拷贝(否则自动生成浅拷贝版本),调用场景为:根据已有对象初始化新对象
  5. 显示声明赋值函数,若已实现深拷贝
  6. 重载二元操作符时,应使用友元函数(若使用成员函数实现则只需传递一个参数,另一个参数是自己)
    • 友元函数/类,是通往私有成员的后门。其设计宗旨是,一种外部函数/类也可以访问类的私有成员
    • 友元函数不属于类,因此实现时,不需要也不能加::
    • 友元函数不能使用this指针,因此使用时通常需要把类的对象作为参数传入
    • 友元函数的典型使用场景是:一个函数需要访问多个类
  7. 重载+返回的是临时对象,因此不能函数返回值类型不能是引用

C++拷贝构造&操作符重载的更多相关文章

  1. 拷贝构造和拷贝赋值、静态成员(static)、成员指针、操作符重载(day06)

    十七 拷贝构造和拷贝赋值 浅拷贝和深拷贝 )如果一个类中包含指针形式的成员变量,缺省的拷贝构造函数只是复制了指针变量的本身,而没有复制指针所指向的内容,这种拷贝方式称为浅拷贝. )浅拷贝将导致不同对象 ...

  2. C++中的赋值操作符重载和拷贝构造函数

    1,关于赋值的疑问: 1,什么时候需要重载赋值操作符? 2,编译器是否提供默认的赋值操作符? 2,关于赋值的疑问: 1,编译器为每个类默认重载了赋值操作符: 1,意味着同类型的类对象可以相互赋值: 2 ...

  3. C++ 进阶5 拷贝构造 深度复制 运算符重载

    C++ 进阶5 拷贝构造 深度复制 运算符重载 20131026 例子: 运行环境是G++ 编译, /* * main.cpp * *  Created on: 2013年10月26日 *      ...

  4. c++ 操作符重载和友元

    操作符重载(operator overloading)是C++中的一种多态,C++允许用户自定义函数名称相同但参数列表不同的函数,这被称为函数重载或函数多态.操作符重载函数的格式一般为: operat ...

  5. C++之旅:拷贝构造与友元

    拷贝构造与友元 拷贝构造是在构造一个对象的时候将已有对象的属性拷贝给新的对象:友元可以让一个类的所有属性(主要是private)对特定的类开放 拷贝构造 如果没有复写拷贝构造函数,系统会帮我们默认生成 ...

  6. [c++基础]3/5原则--拷贝构造函数+拷贝赋值操作符

    /* * main.cpp * * Created on: Apr 7, 2016 * Author: lizhen */ #include <iostream> #include &qu ...

  7. C++ 操作符重载 (operator)

    重载不能改变操作符的优先级 如果一个内建操作符是一元的,那么所有对它的重载仍是一元的.如果是二元的重载后也是二元的 下面看一个有代表性的例子:: 头文件Complex.h: #includeusing ...

  8. C++基础 (4) 第四天 this指针 全局函数和成员函数 友元 操作符重载

    1static强化练习-仓库进货和出货 #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; c ...

  9. C++等号操作符重载

    在新学操作符重载时最令人头疼的可能就是一些堆溢出的问题了,不过呢,只要一步步的写好new 与 delete.绝对不会有类似的问题. 当时我们编译可以通过,但是运行会出错,因为对象s1与s2进行赋值时, ...

随机推荐

  1. 关于金额,重量等浮点数的数据库字段设计(用Int,Long代替浮点数计算)

    金额.重量.成绩等数据库字段推荐使用int或bigint类型. 通常我们数据库设计中金额,重量等涉及到小数位的字段会用float或decimal,mysql还可以用double,但往往每笔金额的计算我 ...

  2. IndexAction.java (Java之负基础实战)

    生成Get and Set 方法: 例如:public String view; 右击view > Source > Generate Getters and Setters...

  3. Effective java -- 2 对于所有对象都通用到方法

    第八条:覆盖equals时请遵守通用约定 什么时候需要覆盖equals方法?类具有自己的逻辑相等概念,并且父类的equals方法不能满足需要.重写equals时需要遵循一下约定: 自反性:非null ...

  4. javascript的字符串操作

    一,把字符串的首字母大写返回一个新的字符串 1.1简单写法,把一个单词的首字母大写 String.prototype.firstUpperCase = function(){ return this[ ...

  5. Spring内部bean无法通过id获取

    内部Bean注入正常,但是直接在context中getBean是得不到的: <?xml version="1.0" encoding="UTF-8"?&g ...

  6. Java泛型类型擦除导致的类型转换问题

    初步结论:泛型类型转换不靠谱: 源码: package com.srie.testjava; public class TestClassDefine4<T> { public stati ...

  7. Oracle基础学习(二)v$session中Command的数字含义

    v$session中Command的数字含义. 1 CREATE TABLE 2 INSERT 3 SELECT 4 CREATE CLUSTER 5 ALTER CLUSTER 6 UPDATE 7 ...

  8. 将 ext_net 连接到 router - 每天5分钟玩转 OpenStack(145)

    上一节完我们创建了外部网络 ext_net,接下来需要将其连接到 Neutron 的虚拟路由器,这样 instance 才能访问外网. 点击菜单 Project -> Network -> ...

  9. svn conflicts: local delete, incoming delete upon update

    svn  st查看更新的时候发现存在conflicts,提示很多 local delete, incoming delete upon update , $:svn st ? C IMIRROR.T3 ...

  10. Salesforce使用truncate清空数据库

    如果想快速的清空MySQL中的表,可以使用Truncate命令.Truncate能够快速的,对数据进行无差别的清空. 在Mysql中使用truncate的语法是TRUNCATE TABLE [Tabl ...