C++中的三大件

C++类中的成员函数的三大件(Big Three):拷贝构造函数,赋值运算符重载函数,析构函数。

拷贝构造函数:用已存在类对象赋值给将要创建对象赋值,创建出新的对象。

一般定义如下:

String(const String&);//参数中的引用不能去掉,否则造成死循环。

赋值运算符重载函数:一般定义为类的成员函数,当类中有指针变量时,通常分四步走,判断是否是自赋值;是的话删除旧空间;创建新空间;用strcpy进行赋值;最终返回*this。

一般定义如下:

const String& operator=(const String&);

析构函数:当对象离开其作用域时,调用析构函数,用于销毁对象释放空间。

一般定义如下:

~String();

为什么要用三大件?主要是为了实现深拷贝。

具体代码如下:

//
//  String.h
//  BigThree
//
//  Created by student on 15/8/14.
//  Copyright (c) 2015年 personals. All rights reserved.
//

#ifndef __BigThree__String__
#define __BigThree__String__

#include <iostream>
#include <string>
using namespace std;

class String{
public:
    String(const char *str = ""); // 通用构造函数
    String(const String &another); // 拷贝构造函数
    ~String(); // 析构函数
    const String& operator =(const String& rhs); // 赋值函数
    friend ostream& operator<<(ostream& os,const String& s); // 输出运算符重载;
    
private:
    char* m_data; // 用于保存字符串
    
};

#endif /* defined(__BigThree__String__) */
//
//  String.cpp
//  BigThree
//
//  Created by student on 15/8/14.
//  Copyright (c) 2015年 personals. All rights reserved.
//

#include "String.h"
String::String (const char *str){
    if (!str) {                   
        m_data = NULL;
    }
    else{
        m_data = new char[strlen(str)+1];
        strcpy(m_data,str);
    }
    cout<<"Constructor is called!\n";
}

String::String (const String &another){
    if(!another.m_data){
        m_data = NULL;
    }
    else{
        m_data = new char[strlen(another.m_data)+1];
        strcpy(m_data,another.m_data);
    }
    cout<<"Copy constructor is called!\n";
}
String::~String(){
    if (m_data!=NULL) {
        delete [] m_data;
    }
    cout<<"Destructor is called!\n";
}

const String& String::operator =(const String &rhs){
    if(this != &rhs){          // >1判断是否是自赋值;
        delete [] m_data;      // >2 删除旧空间;
        if(!rhs.m_data){
            m_data = NULL;
        }
        else{
            m_data = new char[strlen(rhs.m_data)+1]; // >3创建新空间,并实现内容拷贝;
            strcpy(m_data,rhs.m_data);
        }
    }
    cout<<"Assignment operator overloading function is called!\n";
    return *this;  // >4返回*this,方便链式调用;
}

ostream& operator<<(ostream& os,const String& s){
    os<<"string is:"<<s.m_data<<endl;
    return os;
}
//
//  main.cpp
//  BigThree
//
//  Created by student on 15/8/14.
//  Copyright (c) 2015年 personals. All rights reserved.
//

#include <iostream>
#include "String.h"

int main(int argc, const char * argv[])
{

    // insert code here...
    String s1,s2("asdf");    //调用两次构造函数;
    s1 = s2;                //调用赋值运算符重载;
    cout<<"s1 "<<s1<<"s2 "<<s2;
    String s3=s2;           //调用拷贝构造函数(或者String s3(s2));
    cout<<"s3 "<<s3;
    //std::cout << "Hello, World!\n";
    return 0;               //最终调用调用三次析构函数,先析构拷贝构造再析构构造函数;
}

输出结果:

Constructor is called!

Constructor is called!

Assignment operator overloading function is called!

s1 string is:asdf

s2 string is:asdf

Copy constructor is called!

s3 string is:asdf

Destructor is called!

Destructor is called!

Destructor is called!

Program ended with exit code: 0

时间: 2024-12-26 10:54:01

C++中的三大件的相关文章

JavaScript中的三种弹出对话框

JavaScript中的三种弹出对话框 *****本文来自互联网****** 学习过js的小伙伴会发现,我们在一些实例中用到了alert()方法.prompt()方法.prompt()方法,他们都是在屏幕上弹出一个对话框,并且在上面显示括号内的内容,使用这种方法使得页面的交互性更精彩,实际上我们经常会在进行网页浏览时简单这种类型的对话框,在用户与应用程序进行双向交流时,经常要用到对话框.avascript的三种对话框是通过调用window对象的三个方法alert(),confirm()和prom

js oop中的三种继承方法

JS OOP 中的三种继承方法: 很多读者关于js opp的继承比较模糊,本文总结了oop中的三种继承方法,以助于读者进行区分. <继承使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方法.(继承的两方,发生在两个类之间)> 一.通过object实现继承 1:定义父类 function Parent(){} 2:定义子类 funtion Son(){} 3:通过原型给Object对象添加一个扩展方法. Object.prototype.customExtend = function(p

TCP协议中的三次握手和四次挥手(图解)【转】

建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. [更新于2017.01.04 ]该部分内容配图有误,请大家见谅,正确的配图如下,错误配图也不删了,大家可以比较下,对比理解效果更好.这么久才来更新,抱歉!! 错误配图如下: 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源.Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了. 那如何断开连接呢?

.NET中的三种接口实现方式

摘自:http://www.cnblogs.com/zhangronghua/archive/2009/11/25/1610713.html 一般来说.NET提供了三种不同的接口实现方式,分别为隐式接口实现.显式接口实现.混合式接口实现.这三种方式各有各的特点. 首先来看隐式接口实现,这恐怕是我们使用最多的一种接口实现,因为隐匿接口实现是.NET的默认接口实现方式.下面让我们来看一个隐式接口实现的例子: using System; internal class MyClass { public

SQL Server 中的三种分页方式

USE tempdb GO SET NOCOUNT ON --创建表结构 IF OBJECT_ID(N'ClassB', N'U') IS NOT NULL DROP TABLE ClassB GO CREATE TABLE ClassB(ID INT PRIMARY KEY, Name VARCHAR(16), CreateDate DATETIME, AID INT, Status INT) CREATE INDEX IDX_CreateDate ON ClassB(CreateDate)

C语言中的三字母词

C语言中的三字母词(trigraph) 在ANSI C标准中,定义了9个三字母词(trigraph),三字母词就是几个字符的序列,合起来表示另一个字符.三字母词使C语言环境可以在缺少一些必需字符的字符集(比如,一些非常老式的键盘上没有[]{}#\^~|)上实现.也许是由于这些字符集我们基本上用不到,所以在大多数C语言的书籍中,我们都看不到对三字母词的讲解.下图列出了9个三字母词以及它们所代表的的字符. 源代码中的"三字母词",在编译阶段会被替换为"对应的字符".对于

C++ 中的三种类型

C++中一共三种类型 1.C++内置类型,2.1节中讲到的int.double.bool等就是基本的内置类型(低级数据类型): 2.C++还定义了一个内容丰富的抽象数据类型标准库,其中重要的如string.vector,数组和指针等(更高级的抽象数据类型): 3.第三种就是自定义的类类型,前面说过C++ 设计的焦点就是使所定义的类类型的行为可以像内置类型一样自然.

.NET中的三种Timer的区别和用法(转)

最近正好做一个WEB中定期执行的程序,而.NET中有3个不同的定时器.所以正好研究研究.这3个定时器分别是:  //1.实现按用户定义的时间间隔引发事件的计时器.此计时器最宜用于 Windows 窗体应用程序中,并且必须在窗口中使用.  System.Windows.Forms.Timer  // 2.提供以指定的时间间隔执行方法的机制.无法继承此类.  System.Threading.Timer  //3.在应用程序中生成定期事件.  System.Timers.Timer  这三个定时器位

MySQL buffer pool中的三种链

三种page.三种list.LRU控制调优 一.innodb buffer pool中的三种页 1.free page:从未用过的页 2.clean page:干净的页,数据页的数据和磁盘一致 3.dirty page:脏页 SQL执行需求: 1.找free页 2.刷新脏页 1.这个页不是热的数据页(刷冷页) 2.这个页最早修改时间(刷修改时间比较早的页,有可能是热页),方便日志文件的覆盖 3.覆盖冷的clean页 为了实现上述需求,innodb用到链表技术(每种链表一种作用,链的存在意义是为了