拷贝构造,操作符重载



  1. 拷贝构造

#include
<iostream>

#include
<string.h>

using
namespace
std;

class
mystring

{

public:

char
*s;

public:

mystring()

{

s
=
new
char[1024];

cout
<< "mystring"
<< endl;

}

//拷贝构造

mystring(const
mystring
&it)

{

s=
new
char[1024];

memset(s,0,1024);

strcpy(s,it.s);

}

~mystring()

{

cout
<< "~mystring"
<< endl;

}

};

int
main()

{

mystring
str1;

strcpy(str1.s,"hello
world");

//这样的方式仅仅调用了一次构造方法

mystring
str2
=
str1;

//   
mystring
str2;

//   
str2
=
str1; 
//这个过程不是拷贝构造的过程,仅仅是=号操作

cout
<< str2.s
<< endl;

return
0;

}

执行后的效果是:

当把代码改成以下的方式的时候,运行结果例如以下:

#include <iostream>
#include <string.h>
 
using namespace std;
 
class mystring
{
public:
    char *s;
public:
    mystring()
    {
        s = new char[1024];
        cout << "mystring" << endl;
    }
    //拷贝构造
    mystring(const mystring &it)
{
    cout << "copy mystring" << endl;
        s= new char[1024];
        memset(s,0,1024);
        strcpy(s,it.s);
    }
 
    ~mystring()
    {
        cout << "~mystring" << endl;
        delete []s;
}
};
 
int main()
{
    mystring str1;
    strcpy(str1.s,"hello world");
    //这样的方式仅仅调用了一次构造方法
    //mystring str2 = str1;
 
    mystring str2;
    str2 = str1;  //这个过程不是拷贝构造的过程,仅仅是=号操作
 
    cout << str2.s << endl;
    return 0;
}
str1 = str2的本质

2.操作符重载规则

重载操作符函数能够对操作作出新的解释,但原有基本予以不变:

A:不改变操作符的优先级

B:不改变操作符的结合性

C:不改变操作符须要的操作数

D:不能创建新的操作符

成员的语法形式为:

类型
类名::operator op(參数表)

{

//相对于该类定义的操作

}

重载赋值操作符

赋值操作符重载用于对象数据的复制

operator= 必须重载为成员函数

voidoperator = (const classname &it);

classname &operator = (const classname &it);

返回引用会支持例如以下语法:obj1= obj2 = obj3;

3.操作符重载的案例:

#include
<iostream>

#include
<stdlib.h>

#include
<string.h>

using
namespace
std;

class
mystring

{

public:

char
*s;

public:

mystring()

{

s
=
new
char[1024];

cout
<< "mystring"
<< endl;

}

mystring(const
mystring
&it)//深拷贝

{

cout
<< "copy
mystring"
<< endl;

s
=
new
char[1024];

memset(s,
0,
1024);

strcpy(s,
it.s);

}

~mystring()

{

cout
<< "~mystring"
<< endl;

delete
[]s;

}

mystring
operator
=(const
mystring
&it)//重载了一个=号操作符

{

cout
<< "=
operator"
<< endl;

memset(s,
0,
1024);

strcpy(s,
it.s);

//在这个过程中调用了深拷贝的过,这里是以个暂时的拷贝过程,拷贝完毕之后调用深拷贝

return
*this;

}

mystring
operator
=(const
char
*str)//重载了一个=号操作符

{

memset(s,
0,
1024);

strcpy(s,
str);

return
*this;

}

mystring
operator
=(int
i)//重载了一个=号操作符

{

memset(s,
0,
1024);

sprintf(s,
"%d",
i);

return
*this;

}

mystring
operator
+
(const
mystring
&it)//重载了一个+号操作符

{

strcat(s,
it.s);

return
*this;

}

mystring
operator
+
(const
char
*str)//重载了一个+号操作符

{

strcat(s,
str);

return
*this;

}

void
operator
+=(const
char
*str)//

{

strcat(this->s,
str);

}

mystring
operator
+
(int
i)//重载了一个+号操作符,一元操作符重载

{

char
temp[100]
=
{0};

sprintf(temp,
"%d",
i);

strcat(s,
temp);

return
*this;

}

void
operator
<<(const
char
*str)//把<<操作符定义为赋值

{

strcpy(s,
str);

}

void
operator
>>(char
*str)//把<<操作符定义为赋值

{

strcpy(str,
s);

}

mystring
operator
++(int)//重载++操作符的函数int參数是固定

{

int
len
=
strlen(s);

for(int
i
=
0;i
<
len;
i++)

{

s[i]++;//让s的第一个成员char
+
1,就是将s[0]相应字符的ASCII码
+
1

}

return
*this;

}

void
*
operator
new(size_t
size)//假设重载的new,那么必须重载delete

{

//參数size就是sizeof(mystring)的大小.

cout
<< "size
= "
<< size
<< endl;

mystring
*p
=
(mystring
*)malloc(size);

return
p;

}

void
*
operator
new[](size_t
size)//假设重载的new,那么必须重载delete

{

//參数size就是sizeof(mystring)的大小
*
new[x]
+
4个字节.

cout
<< "size
= "
<< size
<< endl;

//mystring
*p
=
(mystring
*)malloc(size);

return
NULL;

}

void
operator
delete[](void
*obj)

{

free((mystring
*)obj);

obj
=
NULL;

}

void
operator
delete(void
*obj)

{

free((mystring
*)obj);//不能直接free一个void
*;

obj
=
NULL;//防止野指针

}

bool
operator
==(const
mystring
&it)

{

if
(strcmp(s,
it.s)
==
0)//假设this->s和it的s同样,就返回true

{

return
true;

}else

return
false;

}

bool
operator
==(const
char
*str)

{

if
(strcmp(s,
str)
==
0)//假设this->s和it的s同样,就返回true

{

return
true;

}else

return
false;

}

//假设返回的是char,代表的是一个右值,右值是不能直接赋值的,

//假设返回的是char的引用,那么[]就能够当左值使用了

char
&operator[](int
index)

{

return
s[index];

}

void
operator
()(const
char
*str)//重载函数调用操作符

{

strcpy(s,
str);

}

void
operator
()(int
i)

{

sprintf(s,
"%d",
i);

}

operator
int()

{

return
atoi(s);

}

friend
mystring
operator
+(const
char
*str,
const mystring
&it);

};

bool
operator
==(const
char
*str,
const
mystring
&it)

{

if
(strcmp(str,
it.s)
==
0)

{

return
true;

}else

return
false;

}

//操作符重载,有一个最基本条件,就是一定有一个一元是一个自己定义的C++类

//假设两个都是基本数据类型操作符重载是非法的

mystring
operator
+(const
char
*str,
const
mystring
&it)

{

mystring
str1;

char
buf[1024]
=
{0};

sprintf(buf,
"%s%s",
str,
it.s);

strcpy(str1.s,
buf);

return
str1;

}

mystring
operator
++(mystring
&it)

{

int
len
=
strlen(it.s);

for(int
i
=
0;i
<
len;
i++)

{

it.s[i]++;//让s的第一个成员char
+
1,就是将s[0]相应字符的ASCII码
+
1

}

return
it;

}

mystring
operator
+(int
i,
const
mystring
&it)

{

mystring
str1;

char
buf[1024]
=
{0};

sprintf(buf,
"%d%s",
i,
it.s);

strcpy(str1.s,
buf);

return
str1;

}

class
demo

{

public:

demo()

{

}

};

void
test(int
i)

{

cout
<< i
<< endl;

}

int
main()

{

//   
mystring
str;

//   
str
<<
"123";

//   
test(str);//导致C++编译器自己主动的配备int()操作符

mystring
*p
=
new
mystring;

delete
p;

//   
mystring
*p
=
(mystring
*)malloc(sizeof(mystring));

//   
free(p);

return
0;

}

int
main04()

{

mystring
str1;

str1
<<
"hello";

mystring
str2;

str2
<<
"hello";

if
("hello"
==
str1)

{

cout
<< "true"
<< endl;

}else

{

cout
<< "fasle"
<< endl;

}

str1[2]
=
‘a‘;

//str1("aaaaaaaa");

str1(10);

cout
<< str1.s
<< endl;

return
0;

}

int
main03()

{

cout
<< "mystring
size ="
<< sizeof(mystring)
<< endl;

mystring
str1;

str1

"hello";

mystring
str2;

str2
=
"
world";

mystring
str3;

//str3
=
str1
+
str2;//对C++编译器来讲,不能识别两个类+是什么含义

//str3
=
str1
+
"aaaaaaaaaaaa";

//str3
=
str1
+
100;

//str3
=
"AAAAA"
+
str1;

str3
=
100
+
str1;

str3
+=
"BBBBBB";

str3
<<
"CCCCC";

char
buf[1024]
=
{0};

str3
>>
buf;

str2
=
str3++;

str2
=
++str3;

mystring
*pstr
=
new
mystring;

delete
pstr;

cout
<< str3.s
<< endl;

return
0;

}

int
main01()

{

mystring
str1;

strcpy(str1.s,
"hello
world");

mystring
str2;

str2
=
str1;//这个过程不是拷贝构造的过程,仅仅是=号操作

//str2.operator
=(str1);//和直接写=号是一摸一样的

cout
<< str2.s
<< endl;

str2
=
"test";//C++编译器不能理解把一个字符串赋给一个类是什么含义

mystring
str3;

str3
=
str2
=
100;

//str3
=
str2.operator
=(100);//上一条语句的等效语法

cout
<< str2.s
<< endl;

return
0;

}

时间: 2024-10-10 07:50:10

拷贝构造,操作符重载的相关文章

C++ 拷贝构造函数和重载赋值操作符相互调用分析 [转]

结论: 从面相对象编程的角度考虑,拷贝构造函数调用重载赋值操作符,重载赋值操作符调用拷贝构造函数的写法都是没有意义的.应该避免. Don't try to implement one of the copying functions in terms of the other. Instead, put common functionality in a third function that both call. ——Effective C++ Third Edition By Scott M

拷贝构造函数 和 赋值操作符重载

什么时候需要定义自己的拷贝构造函数: 当类中包含有,动态分配成员 或者 指针 的时候. 如果使用默认构造函数,则新构造出来的 新类 和 旧类 里面的指针成员 指向同一个空间, 而当其中一个类 清空掉那个空间 .另一个类的指针就会变成野指针(因为空间已经被清空) , 也就是说默认构造函数是复制值(地址也是值) ps.基本数据类型的数组可以直接使用默认复制构造函数.也就是说有涉及到 自行开辟额外空间 的数据类型 和 指针 的类就需要 什么时候调用拷贝构造函数: 1.一个对象以 值传递 的方式 传入

为什么类的拷贝构造参数加引用、重载赋值函数的返回值和参数加引用

class string { public: string(const char *str=NULL); string(const string& str);     //copy构造函数的参数为什么是引用呢? string& operator=(const string & str); //赋值函数为什么返回值是引用呢?参数为什么是引用呢? ~string(); }; 下面我就给大家解释一下: class String1 { public: String1(const char*

类的成员函数(构造、析构、拷贝构造、赋值、运算符重载)的实现

以String类为例实现其成员函数 class String { //友元函数重载运算符 friend ostream& operator<<(ostream &out,String& str); friend istream& operator>>(istream& in, String& str); public: //通用构造函数 String(const char* str) { if(!str) //对m_data加NULL

赋值函数与拷贝构造的差异

C++ 拷贝构造函数 赋值构造函数 ================================= 一句话,赋值函数的前提是对象已定义:而拷贝构造是执行时才会创建一个对象.拷贝构造需要的是深拷贝. 赋值函数一般模式: type& operator =(const type& par) { // (1) 检查自赋值 if( this == &par ) return *this; // (2) 释放原有的内存资源 //(3)分配新的内存资源,并复制内容 ,2.3顺序没讲究,注意释

C++ Primer 学习笔记_26_操作符重载与转换(1)--可重载/不可重载的操作符、成员函数方式重载、友元函数方式重载

C++ Primer 学习笔记_26_操作符重载与转换(1)--可重载/不可重载的操作符.成员函数方式重载.友元函数方式重载 引言: 明智地使用操作符重载可以使类类型的使用像内置类型一样直观! 一.重载的操作符名 像任何其他函数一样,操作符重载函数有一个返回值和一个形参表.形参表必须具有操作符数目相同的形参.比如赋值时二元运算,所以该操作符函数有两个参数:第一个形参对应着左操作数,第二个形参对应右操作数. 大多数操作符可以定义为成员函数或非成员函数.当操作符为成员函数时,它的第一个操作数隐式绑定

C++语言学习(八)——操作符重载

C++语言学习(八)--操作符重载 一.操作符重载基础 1.操作符重载的语法 通过operator关键字可以定义特殊的函数,operator本质是通过函数重载操作符. Type operator operatorname(const Type p1, const Type p2) { Type ret; return ret; } 2.友元函数重载操作符 可以将操作符重载函数声明为友元函数. #include <iostream> using namespace std; class Comp

C++等号操作符重载

在新学操作符重载时最令人头疼的可能就是一些堆溢出的问题了,不过呢,只要一步步的写好new 与 delete.绝对不会有类似的问题. 当时我们编译可以通过,但是运行会出错,因为对象s1与s2进行赋值时,采用浅拷贝,导致对象析构时会对同一块内存空间析构两次.也就是说等号操作符“=”,默认是进行浅拷贝,我们需要对等号操作符进行重载,使其能够进行深拷贝. 同时要重载等号操作符支持链式编程,类如 s3 = s4 = s5;  //操作符使对象连载叠加,与上一篇的return *this 与 return

拷贝构造,深度拷贝,关于delete和default相关的操作,explicit,类赋初值,构造函数和析构函数,成员函数和内联函数,关于内存存储,默认参数,静态函数和普通函数,const函数,友元

 1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.第二种初始化的方式是直接在构造方法里面实现初始化. 案例如下: #include<iostream> //如果声明已经定义,边不会生成 class classA { private: int a; int b; public: //拷贝构造的规则,有两种方式实现初始化 //1.一个是通过在后面:a(x),b(y)的方式实现初始化 //2.第二种初始化的方式是直