C++学习笔记摘录五.docx
《C++学习笔记摘录五.docx》由会员分享,可在线阅读,更多相关《C++学习笔记摘录五.docx(18页珍藏版)》请在冰豆网上搜索。
C++学习笔记摘录五
C++学习笔记
SkySeraph2010-7-31阅读整理
摘自:
接上面C++学习笔记4 继续
22:
#include
usingnamespacestd;
classA
{
public:
A()
{
}
A(A&one)//这里的函数体的意思是默认复制构造函数。
n=one.n是忽略了this->指针编译器会自动加上
//this->n=onoe.n m同n
{
n=one.n;//意思是完成成员A的对考也就是one是别名意思是引用n的内存地址中的值
m=one.m;//同上
}
A(inti,intj)
{
n=i;
m=j;
}
voidprt()
{
cout< }
private:
intn,m;
};
intmain()
{
Aa(2,3);
a.prt();
cout<<"\n";
Ab(a);//这里是复制A对象的值,如果我们没创建构造函数,那么编译器将会自动创建。
我们可以看到输出的值
//和a.prt()是一样的。
这就完成了拷贝
b.prt();
return0;
}
23:
#include
usingnamespacestd;
classA
{
public:
//如果你省略这里的public那么编译器将会认为他是私有的
A(){}//如果你没设置默认构造函数那么编译器会自动创建一个不带参和无函数体的默认构造函数比如这个
A(inti,intj)
{
n=i;
m=j;
}
private:
intn,m;
};
24:
#include
usingnamespacestd;
classA
{
public:
A()
{
cout<<"构造函数执行中...\n";
}
~A()//如果这里我们不定义 那么编译器也会给我们创建一个默认析构函数就是~A(){}这种形式他的函数体为空
{
cout<<"析构函数执行中...\n";
}
};
intmain()
{
A*p=newA;//定义一个指向类A的指针P,用来接受类A创建的对象地址。
deletep;//删除p后会自动调用析构函数。
主要知识点。
也就是delete会自动调用析构函数
return0;
}
25:
#include
usingnamespacestd;
classA
{
public:
explicitA(inta)//explicit关键字的意思是关闭隐式转换,显示转换可以因为隐式转换容易出问题
{
i=a;
cout<<"构造函数执行中..."<
}
~A()
{
cout<<"析构函数执行中..."<
}
voidget()
{
cout<
}
private:
inti;
};
intmain()
{
Ab(33);
b.get();
b=444;//这是简写这里相当于 b=A(444) 将一个对象用括号括起来,在左边放置一个类型,这个是强制类型表达式
//他的右边是一个临时对象,左边是一个对象A,所以他会执行两次析构函数
//A(444)是调用的默认构造函数的A(inta)他只有一个参数所以才执行这个如果多个就必须有相匹配的项目
//(444)是强制把444转为对象A
return0;
}
//显示转换和隐式转换的区别。
显示是b=A(444)隐式是b=444
26:
#include
usingnamespacestd;
classA
{
public:
A()
{
x=newint;
*x=5;
}
~A()
{
deletex;
x=NULL;//删除执行X后吧他赋值为空,避免出错,null就是空的意思,c++中区分大小写
}
A(constA&a)
{
x=a.x;//我们把默认构造函数的这种复制方式叫做成员拷贝又叫浅拷贝。
如果成员里面有指针,
//那么这种方式
}
voidprt() const
{
cout<<*x< }
voidset(inti)
{
*x=i;
}
private:
int*x;
};
intmain()
{
A*j=newA();
cout<<"J:
";
j->prt();
cout< Ab=(*j);
b.prt();
cout<<"J:
";
j->set(22);
cout<<"B:
";
b.prt();
cout< deletej;//在析构了j后内存区域已经被删除那么b被析构的时候就会找不到那快内存区域而导致程序崩溃
return0;
}
27:
#include
usingnamespacestd;
classA
{
public:
A()
{
x=newint;
*x=5;
}
~A()
{
deletex;
x=NULL;
}
A(constA&a)
{
x=newint;//这两行代码定义了一个新的指针,并把X指向了新的内存空间
*x=*(a.x);//这里他们就不是地址的赋值了,而是值的赋值
//以上就是深层复制构造函数。
他把旧的指针的值赋值给新的指针
}
voidprt() const
{
cout<<*x< }
voidset(inti)
{
*x=i;
}
private:
int*x;
};
intmain()
{
A*j=newA();
cout<<"J:
";
j->prt();
cout< Ab=(*j);//这里是深层赋值,而不是浅层赋值
b.prt();
cout<<"J:
";
j->set(22);
cout<<"B:
";
b.prt();
cout< deletej;//所以当这里被删除的时候就不会引起程序崩溃了。
因为j和b都是分别指向不同的内存空间。
所以J被删除后
//不会影响到b b也不会成为迷途指针
return0;
}
运算符重载.
1:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;}
~A(){}
intget()const{returnn;}
voidset(intx)
{
n=x;
}
private:
intn;
};
intmain()
{
Aa;
cout<<"a:
"< //如果这里有a++那么就会出错。
因为对象是不能自加的只有变量可以
return0;
}
2:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;}
~A(){}
intget()const{returnn;}
voidset(intx)
{
n=x;
}
voidadd()
{
++n;//在成员函数中进行自加可以解决上面的问题
}
private:
intn;
};
intmain()
{
Aa;
cout<<"a:
"< a.add();//这里就可以通过调用add函数来实现i的自加
cout<<"a:
"< return0;
}
3:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;}
~A(){}
intget()const{returnn;}
voidset(intx)
{
n=x;
}
voidadd()
{
++n;
}
voidoperator++()//operator关键字。
可以实现对象a的自加。
他的前面是返回类型后面是重载运算符++就是他要做的事
{
++n;//这里是函数体才是这个函数所执行的部分,operator是个函数所有要加()和{}
}
private:
intn;
};
intmain()
{
Aa;
cout<<"a:
"< a.add();
cout<<"a:
"< ++a;//这里就可以实现a的自加,operator的作用就是在这里。
也就是operator的函数调用
cout<<"a:
"< return0;
}
/*为什么上面的功能能够这样实现。
因为C++中把所有表达式都认为是operator
比如 1+2 那么C++会自动翻译为operator+(1,2)然后他会寻找是否有这个默认匹配的参数会找到
operator+(int,int)双int型
同理。
其实++a的意义就是 i.operator++() operatori++这个就是对象操作操作
*/
4:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;}
~A(){}
intget()const{returnn;}
voidset(intx)
{
n=x;
}
voidadd()
{
++n;
}
Aoperator++()
{
++n;
At;//创建一个临时对象
t.set(n);
returnt;//返回一个对象T
}
private:
intn;
};
intmain()
{
Aa;
cout<<"a:
"< a.add();
cout<<"a:
"< An=++a;//将自加后的对象赋给另一个对象由于是对象赋值所以没有报错也就是调用Aoperator++这个函数并且把++a变成3赋值给n
//因为n被初始化为1后又被++n变成2然后到An=++a++a又变成3n就等于3所以输出3
cout<<"n:
"< return0;
}
//这个是解决对象之间的赋值问题,也就是创建临时对象的作用
5:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;cout<<"构造函数运行中\n";}//为了方便查看所以加上cout语句
A(inti)//创建一个带参数的临时构造函数
{
n=i;
cout<<"带参数的构造函数运行中\n";//为了方便查看所以加上cout语句
}
~A(){cout<<"析构函数运行中\n";}//为了方便查看所以加上cout语句
intget()const{returnn;}
voidset(intx)
{
n=x;
}
voidadd()
{
++n;
}
Aoperator++()
{
++n;
returnA(n);//这里简化了步骤直接调用带参数的默认构造函数A(N)来返回给对象A也就是2
}
private:
intn;
};
intmain()
{
Aa;
cout<<"a:
"< a.add();
cout<<"a:
"< An=++a;
cout<<"n:
"< return0;
}
//以上不创建临时对象而实现对象之间的赋值,但是其实,他是自己创建了一个临时对象,我们的操作只是简化了此步骤而已
//通过提示可以看出带参数的构造函数运行中在C++中一旦创建一个对象,那么就会给此对象开辟一个空间,让他存放此对象
//而程序执行完毕也会释放该对象那么会调用析构函数
6:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;cout<<"构造函数运行中\n";}
A(inti)
{
n=i;
cout<<"带参数的构造函数运行中\n";
}
~A(){cout<<"析构函数运行中\n";}
A(constA&s){this->n=s.n;cout<<"复制构造函数执行中....\n";}//演示,因为没有这句话那么你会看到两个析构函数执行,但是却只有一个默认构造函数执行,那另外一个析构函数就是由复制构造函数执行后得来的this->n=s.n可以缩写n=s.n
//const是定义常量因为复制的s不会被改变。
A&s就是复制构造函数,也就是s其实就是复制了A的对象的内存空间地址的值。
在上一节中有讲到
intget()const{returnn;}
voidset(intx)
{
n=x;
}
voidadd()
{
++n;
}
constA&operator++()//使用CONST指针定义常量,如果你不想让下面的An=++++a就加上CONST这样operator就会以别名的方式返回源对象,也就是operator对象
{
++n;
return*this;//这里this前面要加*要不然他只是返回一个指针而不是对象
}
private:
intn;
};
intmain()
{
Aa;
cout<<"a:
"< a.add();
cout<<"a:
"< An=++a;//通过提示文字可以看出,是这里执行的复制构造函数
cout<<"n:
"< return0;
}
7:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;cout<<"构造函数运行中\n";}
A(inti)
{
n=i;
cout<<"带参数的构造函数运行中\n";
}
~A(){cout<<"析构函数运行中\n";}
A(constA&s){this->n=s.n;cout<<"复制构造函数执行中....\n";}
intget()const{returnn;}
voidset(intx)
{
n=x;
}
voidadd()
{
++n;
}
constA&operator++()
{
++n;
return*this;
}
constAoperator++(into)//由于临时对象超出作用域后会被虚构掉,而我们使用引用方式会返回一个空值所以要去掉引用,而用值的方式来返回!
(into)不做任何动作他是毫无意义的可以理解为只是告诉编译器这个是一个后自加!
{
Atemp(*this);//先创建一个临时对象并且获取原始对象的值
++n;//this->已经被省略。
returntemp;//返回临时对象 从这里就是实现先返回在自加操作就是下面的a++
}
private:
intn;
};
intmain()
{
Aa;
cout<<"a:
"< a.add();
cout<<"a:
"< An=a++;
cout<<"a:
"< cout<<"n:
"< return0;
}//这个就是验证效果的说明!
也是重载后置自加运算符
8:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;cout<<"构造函数运行中\n";}
A(inti)
{
n=i;
cout<<"带参数的构造函数运行中\n";
}
~A(){cout<<"析构函数运行中\n";}
A(constA&s){this->n=s.n;cout<<"复制构造函数执行中....\n";}
intget()const{returnn;}
voidset(intx)
{
n=x;
}
Aadd(constA&r)//修改后的ADD函数这里不在返回无返回值VOID而是返回一个构造函数A并且定义A的别名r
{
returnA(n+r.get());//返回n+r.get()r.get()就是上面intgetn所返回的值。
并且和n相加然后在传递给A
}
constA&operator++()
{
++n;
return*this;
}
constAoperator++(into)
{
Atemp(*this);
++n;
returntemp;
}
private:
intn;
};
intmain()
{
Aone
(1),two
(2),three;//定义三个对象并且初始化前两个对象的值。
three=one.add(two);//调用方式已知two是2one是1那么add函数执行就把2的值传递到r.get()n是1那么就是1+2
cout<<"one:
"< cout<<"two:
"< cout<<"three:
"< return0;//这里输出结果
}//重载加法运算函数这个例子没有用到operator
下面才是方便简单直观的例子:
#include
usingnamespacestd;
classA
{
public:
A(){n=1;cout<<"构造函数运行中\n";}
A(inti)
{
n=i;
cout<<"带参数的构造函数运行中\n";
}
~A(){cout<<"析构函数运行中\n";}
A(constA&s){this->n=s.n;cout<<"复制构造函数执行中....\n";}
intget()const{returnn;}
voidset(intx)
{
n=x;
}
constAoperator+(constA&r)//再次修改只需要把add换成operator即可并且前面加上const加上CONST可以防止结果被修改。
当然如果你想要修改那么不加
{
returnA(n+r.get());
}
constA&operator++()
{
++n;
return*this;
}
constAoperator++(into)
{
Atemp(*this);
++n;
returntemp;
}
private:
intn;
};
intmain()
{
Aone
(1),two
(2),three;
//three=one.add(two);//这里注释掉,如果用operator使用下面的就更加方便
three=one+two;//这样的操作就更加直观了,如果你上面没加常量那么这里还可以修改为++(one+two)
cout<<"one:
"< cout<<"two:
"< cout<<"three:
"< return0;
}//重载加法运算函数这个是运用到的是不是更直观?