这几天都没怎么复习。。今天感觉不行了要挂了,赶快看两眼,做几道oj。。。
题外话:
因为下学期报了图形学,感觉就难顶,这几天都在摸鱼 ,石乐志一样疯狂写一个mc的渲染的着色器,算是当作预习一下opengl吧。。。 所以博客咕咕了。。。
目前进度只写完了辉光和阴影。。。
预告一蛤,以后有空的话,我会专门写一个教学专栏,从0到1,写一个mc的着色器,一步一步完成各种特效,什么阴影啊辉光啊屏幕空间反射啊体积云啊等等
咕
好了扯远了。 婷芷 还是来复习拷贝构造函数与运算符重载罢(无慈悲
拷贝构造函数是一个头疼的点,因为每当对象创建时,都需要它。我们习惯于写 int a = 123; 其实这就是一种拷贝构造函数,将值为123的int类型,赋值给变量a,本质是创建了新的变量。
因为灿哥对拷贝构造函数有一手的,所以我向他请教了一些这方面的姿势
它的函数名与类名相同,但它只有一个参数,即同类的一个对象的引用。同时也说明了:不允许有形如 X( X r)的构造函数
Cat( Cat& c );
//或
Cat( const Cat& c ); // 一般用这种,防止有人偷偷摸摸改c的数据
在创建新对象时,当使用一个已知的对象来初始化另一个对象时,系统会自动隐式地调用拷贝构造函数。
Cat cat2(cat1); //调用拷贝构造函数
如果你不定义拷贝构造函数,那么使用 Cat cat2(cat1) 时,可以简单理解为:把cat1的简单数据原封不动地复制到cat2里,但不做其他操作。
Cat (int age_) {age=age_;}
Cat cat1(5); //小猫1的年龄是5
Cat cat2(cat1); //调用拷贝构造函数,小猫2的年龄也是5
很麻烦,乖乖自己写拷贝构造函数
Cat cat1("伞兵1号"); //小猫1的名字是伞兵1号
Cat cat2(cat1); //调用拷贝构造函数,小猫2的名字也是伞兵1号
有3种情况
class Cat {
char *name;
public:
CPerson() {}
Cat(char *name_) {
name=new char[strlen(n)+1];
strcpy(name,n);
}
};
如果通过某种方式改变cat1的name,那么cat2的name也随之改变
class Cat {
char name[10];
public:
CPerson() {}
Cat(char *name_) {
strcpy(name,n);
}
};
如果通过某种方式改变cat1的name,那么cat2的name不会改变
同用char[]
都是关于地址的知识,不用多说了8
如果你写的拷贝构造函数涉及内存操作或者数组,书本上称之为深拷贝。
若类中的指针数据是在定义时就分配空间的,则在构造方法中也不需要分配空间
#include
#include
#include
using namespace std;
class CPerson {
//在构造函数前就分配空间
char *name=new char[10],*address=new char[10];
public:
CPerson();
CPerson(char *n,char *a) {
strcpy(name,n);
strcpy(address,a);
}
CPerson(CPerson &r_p) {
//这种写法不用分配空间
//name=new char[20];
//address=new char[20];
strcpy(name,r_p.name);
strcpy(address,r_p.address);
}
void print() {
cout<<name<<","<<address<<endl;
}
void setName(char* n) {
strcpy(name,n);
}
};
int main() {
CPerson c1("zhangsan","shenda");
c1.print();
CPerson c2(c1);
c2.print();
c2.setName("lisi");
cout<<endl;
c1.print();
c2.print();
}
若类中的指针数据,是在构造方法中分配空间的,则拷贝构造函数中也要分配空间
#include
#include
#include
using namespace std;
class CPerson {
char *name,*address;
public:
CPerson() {
//在构造函数里才分配空间
name=new char[10];
address=new char[10];
}
CPerson(char *n,char *a) {
name=new char[10];
address=new char[10];
strcpy(name,n);
strcpy(address,a);
}
CPerson(CPerson &r_p) {
//再写一遍,因为新的对象是在构造函数里进行内存分配 的
name=new char[20];
address=new char[20];
strcpy(name,r_p.name);
strcpy(address,r_p.address);
}
void print() {
cout<<name<<","<<address<<endl;
}
void setName(char* n) {
strcpy(name,n);
}
};
int main() {
CPerson c1("zhangsan","shenda");
c1.print();
CPerson c2(c1);
c2.print();
c2.setName("lisi");
cout<<endl;
c1.print();
c2.print();
}
若用string类型来处理字符串,则是安全的(当成int那种类型就行),不需要提供拷贝构造函数
这种方法万事大吉,无脑操作就行。懒狗(指zwc 我自己 )最爱
值得注意的是,使用vecrot,deque等线性容器,也可以类似string一样不考虑内存的分配,而且线性容器可以存储任何数据类型,直接拷贝即可。
关于运算符重载,当时再第一遍学习的时候,有更详细的理解:【c++运算符重载简单讲解】
在很多时候,我们希望通过运算符来表达类之间的运算关系,比如有分数类 Fraction,我们希望
Fraction f1, f2, f3;
f3 = f1 + f2;
而不是
f3 = add(f1, f2);
显然两者应该得到相同的运算结果,而前者的代码可读性更好。于是有人一拍脑袋,想:
f3 = f1 + f2,左操作数是 f1,那么和 add(f1, f2) 一样,如果把 + 运算符当作函数,那 + 运算符等同于 add函数(其实本质上就是把运算符看作函数调用即可)。
在一个对象的运算符重载中,默认左值就是该对象本身。而单目运算符不需要右操作数。
重载前增运算符,因为是单目运算符,因为不需要操作数,参数列表填空即可。
class Cat
{
int age;
public:
Cat operator ++ ()
{
age++;
}
};
虽说单目运算符不需要右操作数,但是为了和上面的前自增(++i)区分,还是在参数列表里面加上一个int。除此之外,因为后++操作是在加之前就返回结果,所以我们需要保存操作之前的结果。8 door ,康 code ⑨ dong 了。
class Cat
{
int age;
public:
Cat operator ++ (int)
{
Cat temp = (*this); // 先复制自己
age++; // 操作
return temp; // 返回增加前的自己
}
};
双目运算符,默认形参为右操作数,左操作数为对象本身。
class Day
{
int date;
public:
Day(){}
Day(int d){date=d;}
Day operator + (Day& d2)
{
return Day(d2.date+date);
}
};
注:右操作数,即形参,可以是任何类型。
一般都是在需要cout自定义类型的时候用的。友元函数运算符重载的最大特点就是:当前类要作为右操作数时,使用友元函数运算符重载
以下例子演示了重载cout以输出自定义类型:
class People
{
private:
string name;
int age;
public:
People(){}
People(string na, int ag){name=na;age=ag;}
friend ostream& operator << (ostream& os, const People& p)
{
os<<"我的名字是:"<<p.name<<" 我的年龄是:"<<p.age;
return os;
}
};
int main()
{
People p("下北泽医科大学李田所", 24);
cout<<p<<endl;
return 0;
}
不细了,自己品
class test
{
vector<int> v{1,2,3,4,5};
public:
int& operator [] (int index)
{
return v[index];
}
};
int main()
{
test t;
cout<<t[1]<<endl;
return 0;
}
Fraction类的基本形式如下:
要求如下:
1.实现Fraction类;common_divisor()和contracted()函数体可为空,不实现具体功能。
2.编写main函数,初始化两个Fraction对象的,计算它们之间的加减乘除。
第1行:依次输入第1个和第2个Fraction对象的分子和分母值。
每行依次分别输出加减乘除计算后的Fraction对象(直接输出分数值,不需要约简)。
1 3 2 5
fraction=11/15
fraction=-1/15
fraction=2/15
fraction=5/6
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Fraction
{
private:
int fz, fm;
public:
Fraction(){fz=1; fm=1;}
Fraction(int z, int m){fz=z; fm=m;}
friend ostream& operator << (ostream& os, const Fraction& f)
{
os<<f.fz<<"/"<<f.fm;
return os;
}
Fraction operator + (const Fraction f2)
{
int newfm = fm*f2.fm;
int newfz = fz*f2.fm + f2.fz*fm;
return Fraction(newfz, newfm);
}
Fraction operator - (const Fraction f2)
{
Fraction f2_neg = Fraction(-f2.fz, f2.fm);
return (*this) + f2_neg;
}
Fraction operator * (const Fraction f2)
{
return Fraction(fz*f2.fz, fm*f2.fm);
}
Fraction operator / (const Fraction f2)
{
Fraction f2_rev = Fraction(f2.fm, f2.fz);
return (*this) * f2_rev;
}
};
int main()
{
int fz1, fm1, fz2, fm2;
cin>>fz1>>fm1>>fz2>>fm2;
Fraction f1(fz1, fm1), f2(fz2, fm2);
cout<<"fraction="<<(f1+f2)<<endl;
cout<<"fraction="<<(f1-f2)<<endl;
cout<<"fraction="<<(f1*f2)<<endl;
cout<<"fraction="<<(f1/f2)<<endl;
return 0;
}
假定一个时钟包含时、分、秒三个属性,取值范围分别为011,059,0~59,具体要求如下:
1、用一元运算符++,并且是前增量的方法,实现时钟的调快操作。例如要把时钟调快5秒,则执行5次” ++<对象> “ 的操作
2、用一元运算符–,并且是后增量的方法,实现时钟的调慢操作。例如要把时钟调慢10秒,则执行10次” <对象>-- “的操作
3、用构造函数的方法实现时钟对象的初始化,用输出函数实现时钟信息的输出
clock是系统内部函数,所以不要用来做类名或者其他
第一行输入时钟的当前时间时、分、秒
第二行输入t表示有t个示例
第三行输入t个整数x,如果x为正整数,则表示执行调快操作,使用重载运算符++;如果x为负整数,则表示执行调慢操作,使用重载运算符–
每次的调快或调慢操作都是承接上一次调整后的结果进行,例如先调快10秒,再调慢2秒,那么调慢2秒是接着调快10秒后的结果进行的
每行输出每个时钟调整操作后的时分秒
11 58 46
4
5 70 -22 -55
11:58:51
0:0:1
11:59:39
11:58:44
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Clock
{
private:
int h, m, s;
public:
Clock(){}
Clock(int H, int M, int S){h=H;m=M;s=S;}
friend ostream& operator << (ostream& os, Clock c)
{
os<<c.h<<":"<<c.m<<":"<<c.s;
}
void add()
{
s++;
if(s==60) s=0, m++;
if(m==60) m=0, h++;
if(h==12) h=0;
}
void sub()
{
s--;
if(s==-1) s=59, m--;
if(m==-1) m=59, h--;
if(h==-1) h=11;
}
// x = ++Clock
Clock operator ++ ()
{
add();
return (*this);
}
// x = Clock++
Clock operator ++ (int)
{
Clock cp = (*this);
add();
return cp;
}
// x = --Clock
Clock operator -- ()
{
Clock cp = (*this);
sub();
return cp;
}
// x = Clock--
Clock operator -- (int)
{
Clock cp = (*this);
sub();
return cp;
}
};
int main()
{
int h,m,s,t,v;
cin>>h>>m>>s;
Clock c(h,m,s);
cin>>t;
while(t--)
{
cin>>v;
if(v>0)
{
while(v--) c++;
} else
{
v = -v;
while(v--) c--;
}
cout<<c<<endl;
}
return 0;
}