来自同济医院的问候
目录
01:对象创建
001.cc
003size.cc
02:对象销毁
004pointer.cc
005destroytime.cc
03:本类型对象的复制
3.1 拷贝构造函数
006cp.cc
007cptime.cc
008recursion.cc
009rightleft.cc
3.2 赋值运算符函数
010thispointer.cc
011operator.cc
3.3 三合成原则
作业喵:
01,关于对象概念的描述中,( )是错误的。 A
02,有关析构函数的说法不正确的是( ) C
03,对类的构造函数和析构函数描述正确的是( )。 A
04,有关类的说法不正确的是____。 D
05,一个空类对象占据的空间有多大?会自动创建哪些函数呢?
06,什么情况下,会调用拷贝构造函数?
07,什么是拷贝构造函数,其形态是什么,参数可以修改吗?
08,什么是赋值运算符函数,其形态是什么?什么情况下需要手动提供赋值运算符函数呢?
09,写出下面程序的运行结果()
10,设已经有A,B,C,D 4个类的定义,程序中A,B,C,D析构函数调用顺序为? ABDC(坏)
11,定义一个学生类,其中有3个数据成员:学号、姓名、年龄,以及若干成员函数。同时编写main函数,使用这个类,实现对学生数据的复制、赋值与输出。
01:对象创建
001.cc
#include <iostream>
using std::cout;
using std::endl;class Point{
public:Point():_ix(0),_iy(0){cout<<"Point()"<<endl;}Point(int x,int y=1):_ix(x),_iy(y){cout<<"Point(int ,int)"<<endl;}//不是严格意义的初始化,本质是赋值/* Point(int x,int y){ *//* _ix=x; *//* _iy=y; *//* cout<<"Point(int ,int )"<<endl;} */void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:int _ix;int _iy;
};
void test(){Point pt1;Point pt2(5);Point pt(1,2);pt1.print();pt2.print();pt.print();
}int main(void)
{test();return 0;
}
003size.cc
#include <iostream>
using std::cout;
using std::endl;#pragma pack(4)class A{int _num;double _price;
};
class B{int _num;int _price;
};
class C{int _num;int _num1;double _price;
};
class D{int _num;double _price;int _num1;
};
class E{double _e;char _eArr[20];double _e1;int _e2;
};
class F{char _fArr[20];
};
class G{int num;
};
class H{char _gArr[20];int _g1;int _g2;
};
class I {};
void test(){cout<<sizeof(A)<<endl;cout<<sizeof(B)<<endl;//16 8cout<<sizeof(C)<<endl;cout<<sizeof(D)<<endl;//16 24cout<<sizeof(E)<<endl;cout<<sizeof(F)<<endl;//48 24cout<<sizeof(G)<<endl;cout<<sizeof(H)<<endl;cout<<endl;I i1,i2;cout<<&i1<<" "<<&i2<<endl;cout<<sizeof(I)<<endl;
}int main(void)
{test();return 0;
}
02:对象销毁
004pointer.cc
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;class Computer{
public:Computer(const char* brand,double price): _brand(new char[strlen(brand)+1]()), _price(price){strcpy(_brand,brand);// 否则没有赋值喵,不输出cout<<"Computer"<<endl;}~Computer(){if(_brand){delete [] _brand; //coution_brand=nullptr; //加上,信任行为喵}cout<<"~Computer"<<endl;}void printBrandPrice(){cout<<"brand:"<<_brand<<"\t\t";cout<<"price:"<<_price<<endl;}
private:/* char _brand[20]; */char* _brand;double _price;
};void test(){Computer pc("dell",20000);pc.printBrandPrice();//对象销毁时一定会调用析构函数,析构函数执行完,对对象没有被销毁//defecate indiscriminately pc.~Computer();/* pc.printBrandPrice(); //locked */cout<<"over "<<endl;
}
void test01(){const char *p="i love xixi";int * pp=nullptr;cout<<p<<endl;cout<<pp<<endl; //0p=nullptr;//C++会自动访问char*类型指针,此处访问了空指针/* cout<<p<<endl; */cout<<"OK OK OK"<<endl;
}
int main(void)
{test();test01();return 0;
}
005destroytime.cc
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;class Computer{
public:Computer(const char* brand,double price): _brand(new char[strlen(brand)+1]()), _price(price){strcpy(_brand,brand);// 否则没有赋值喵,不输出cout<<_brand<<"\t\t"<<"Computer"<<endl;}~Computer(){cout<<_brand<<"\t\t";if(_brand){delete [] _brand; //coution_brand=nullptr; //加上,信任行为喵}cout<<"~Computer"<<endl;}void printBrandPrice(){cout<<_brand<<"\t";cout<<_price<<endl;}
private:/* char _brand[20]; */char* _brand;double _price;
};Computer pc_static("huipu__1",40000);
void test(){Computer pc("dell__2",20000);pc.printBrandPrice();Computer pc_kaixin("honor__3",0);pc_kaixin.printBrandPrice();static Computer pc_jiajia("vsus__4",10000);pc.printBrandPrice();pc_jiajia.printBrandPrice();pc_static.printBrandPrice();Computer* p_new=new Computer("lengion__5",8000);p_new->Computer::printBrandPrice();delete p_new;p_new=nullptr;//坏 后创建的先销毁
}
void test01(){
}
int main(void)
{test();test01();return 0;
}
03:本类型对象的复制
3.1 拷贝构造函数
006cp.cc
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;class Computer{
public:Computer(const char* brand,double price): _brand(new char[strlen(brand)+1]()), _price(price){strcpy(_brand,brand);// 否则没有赋值喵,不输出cout<<_brand<<"\t\t"<<"Computer"<<endl;}Computer(const Computer & pc): _brand(new char[strlen(pc._brand)+1]()), _price(pc._price){strcpy(_brand,pc._brand);// 否则没有赋值喵,不输出cout<<_brand<<"\t\t"<<"Copy Computer"<<endl;}~Computer(){cout<<_brand<<"\t\t";if(_brand){delete [] _brand; //coution_brand=nullptr; //加上,信任行为喵}}void printBrandPrice(){cout<<_brand<<"\t";cout<<_price<<endl;}
private:/* char _brand[20]; */char* _brand;double _price;
};void test(){int x=10;int y=x;cout<<x<<endl;cout<<y<<endl;Computer pc("dell",20000);pc.printBrandPrice();/* Computer pp=pc; */Computer pp(pc);pp.printBrandPrice();//坏,double free//original cpy浅拷贝喵}int main(void)
{test();return 0;
}
007cptime.cc
#include <iostream>
using std::cout;
using std::endl;class Point{
public:Point():_ix(0),_iy(0){cout<<"Point()"<<endl;}Point(int x,int y=1):_ix(x),_iy(y){cout<<"Point(int ,int)"<<endl;}Point(const Point & p):_ix(p._ix),_iy(p._iy){cout<<"Point(Point &)"<<endl;}void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:int _ix;int _iy;
};//Point p=pt3
void func(Point p){p.print();
}
//第二种调用时机 实参和形参都是对象(用实参初始化形参的过程也会调用拷贝构造)
//避免多余复制,写成引用形式
void func01(Point & p){p.print();
}
Point pp(258,258);
Point func02(){ return pp; }
//函数的返回值时对象时,执行return语句会调用拷贝构造
Point & func03(){ return pp; }
//避免这次复制可以将返回值写为引用
//caution live_timevoid test(){Point pt1;Point pt2(5);Point pt(1,2);Point pt3(pt1);//第一种调用时机 初始化cout<<endl;func(pt3);func01(pt3);//第2种调用时机 cout<<endl;func03().print();func02().print();//第3种调用时机 /* pt1.print(); *//* pt2.print(); *//* pt.print(); *//* pt3.print(); */
}int main(void)
{test();return 0;
}
008recursion.cc
#include <iostream>
using std::cout;
using std::endl;class Point{
public:Point():_ix(0),_iy(0){cout<<"Point()"<<endl;}Point(int x,int y=1):_ix(x),_iy(y){cout<<"Point(int ,int)"<<endl;}/* Point(const Point & p) *//* :_ix(p._ix),_iy(p._iy) *//* {cout<<"Point(Point &)"<<endl;} *//* Point( Point & p) *//* :_ix(p._ix),_iy(p._iy) *//* {cout<<"Point(Point &)"<<endl;} *///保证右操作数不被修改,为了能够复制临时对象的Point(const Point p):_ix(p._ix),_iy(p._iy){cout<<"Point(Point &)"<<endl;}//const Point p=pt1,触发拷贝构造函数,陷入递归拷贝喵void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:int _ix;int _iy;
};void test(){Point pt1(30,50);Point pt3(pt1);pt1.print();/* pt3.print(); *///error /* Point pt4=Point(20,20); *//* pt4.print(); *///坏,我的好想能跑
}int main(void)
{test();return 0;
}
009rightleft.cc
#include <iostream>
using std::cout;
using std::endl;class Point{
public:Point():_ix(0),_iy(0){cout<<"Point()"<<endl;}Point(int x,int y=1):_ix(x),_iy(y){cout<<"Point(int ,int)"<<endl;}Point(const Point & p):_ix(p._ix),_iy(p._iy){cout<<"Point(Point &)"<<endl;}void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:int _ix;int _iy;
};void test(){int a=10;int b=20;cout<<&a<<endl;cout<<&(++a)<<endl;//左值 能取地址/* cout<<&(a++)<<endl; *//* cout<<&(a+b)<<endl; *///右值 不能 (临时变量/匿名对象,临时对象,字面值//&1 存在与指令系统,不存在内存中Point pt(1,1);cout<<&pt<<endl;cout<<endl;int & ref=a;const int & ref1=b;/* int & ref2=a+b; *///no const=left//const = left or rightconst int & ref4=a+b;/* printf("%p\n",ref); *//* printf("%p\n",ref1); *//* printf("%p\n",ref4); */
}int main(void)
{test();return 0;
}
3.2 赋值运算符函数
010thispointer.cc
#include <iostream>
using std::cout;
using std::endl;class Point{
public:Point():_ix(0),_iy(0){cout<<"Point()"<<endl;}Point(int x,int y=1):_ix(x),_iy(y){cout<<"Point(int ,int)"<<endl;}Point(const Point & p):_ix(p._ix),_iy(p._iy){cout<<"Point(Point &)"<<endl;}//Point * const this//不能修改指向,”本对象“的地址//隐藏成员函数参数Point & operator=(const Point & p){cout<<"operator="<<endl;/* this->_ix=p._ix; *//* this->_iy=p._iy; */_ix=p._ix;_iy=p._iy;return *this;}void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:int _ix;int _iy;
};void test(){Point p(10,30);Point p1;p1.print();p1=p;/* pt.operator=(pt2);//本质形式 */p1.print();cout<<endl;int x=10,y=100;cout<<&(x=y)<<endl;cout<<&x<<endl;
}int main(void)
{test();return 0;
}
011operator.cc
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;class Computer{
public:Computer(const char* brand,double price): _brand(new char[strlen(brand)+1]()), _price(price){strcpy(_brand,brand);// 否则没有赋值喵,不输出}Computer(const Computer & pc): _brand(new char[strlen(pc._brand)+1]()), _price(pc._price){strcpy(_brand,pc._brand);// 否则没有赋值喵,不输出}Computer & operator=(const Computer & c){cout<<"operator ="<<endl;if(this!=&c){//1 考虑自赋值的情况delete [] _brand;//2 回收原本管理的堆空间_brand=new char[strlen(c._brand)+1]();strcpy(_brand,c._brand);//3 深拷贝_price=c._price;}return *this;//4 返回本对象}~Computer(){if(_brand){delete [] _brand; //coution_brand=nullptr; //加上,信任行为喵}}void printBrandPrice(){cout<<_brand<<"\t";cout<<_price<<endl;}
private:/* char _brand[20]; */char* _brand;double _price;
};void test(){Computer pc("dell",20000);Computer pc1("cici",20000);pc.printBrandPrice();/* Computer pp=ps; */Computer pp(pc);pp.printBrandPrice();//坏,double free//original cpy浅拷贝喵pc=pc;pc.printBrandPrice();pc=pc1;pc.printBrandPrice();}int main(void)
{test();return 0;
}
3.3 三合成原则
作业喵:
01,关于对象概念的描述中,( )是错误的。 A
-
A对象就是C语言中的结构体
-
B对象是状态和操作的封装体
-
C对象之间的信息传递是通过消息进行的
-
D对象是某个类的一个实例
02,有关析构函数的说法不正确的是( ) C
-
A析构函数有且只有一个
-
B析构函数无任何函数类型
-
C析构函数和构造函数一样可以有形参
-
D析构函数的作用是在对象被撤销时收回先前分配的内存空间
03,对类的构造函数和析构函数描述正确的是( )。 A
-
A构造函数可以重载,析构函数不能重载
-
B构造函数不能重载,析构函数可以重载
-
C构造函数可以重载,析构函数也可以重载
-
D构造函数不能重载,析构函数也不能重载
04,有关类的说法不正确的是____。 D
-
A类是一种用户自定义的数据类型
-
B只有类中的成员函数才能存取类中的私有数据
-
C在类中,如果不作特别说明,所有的数据均为私有类型
-
D在类中,如果不作特别说明,所有的成员函数均为公有类型
05,一个空类对象占据的空间有多大?会自动创建哪些函数呢?
空类:1个字节,仅仅是编译器的一种占位机制
自动创建的函数:默认无参构造,默认析构,默认拷贝构造(浅拷贝),赋值运算符函数(浅拷贝的那种喵)
06,什么情况下,会调用拷贝构造函数?
1,用已经存在的对象给新建的对象初始化
(以下为不看代码十分抽象内容)
2,函数参数(实参和形参的类型都是对象),形参与实参结合时(实参初始化形参)
避免不必要的拷贝,可以使用引用作为参数
3,函数的返回值是对象(return 会 copy)
避免多余拷贝,用引用作为返回值,确保返回值的生命周期大于函数的生命周期
07,什么是拷贝构造函数,其形态是什么,参数可以修改吗?
1,用一个已经存在的同类型的对象来初始化新对象的 构造函数
2,类名 (const 类名 & )
3,不可以
3.1 不可以去掉引用符号(遇到第二种调用时机“形参实参都是对象,用实参初始化形参”的时候,会再一次调用拷贝构造,导致递归调用
3.2 不可以去掉const (1,确保右操作数的数据成员不会被改变,2,为了能够赋值临时对象的内容,非const引用不能绑定临时变量)
08,什么是赋值运算符函数,其形态是什么?什么情况下需要手动提供赋值运算符函数呢?
1,用已经创建的对象给另一个对象赋值的时候,会调用赋值运算函数(没有自定义时,系统会提供一个默认版本(浅拷贝版本))
2,类名 & operator = (const 类名 &)
3,当拷贝构造,析构函数,赋值运算符手动定义了其中任何一个,其他两个也都需要手动定义
09,写出下面程序的运行结果()
class Sample
{int i;
public:Sample();Sample(int val);void Display();~Sample();
};Sample::Sample()
{cout << "Constructor1" << endl;i=0;
}Sample::Sample(int val)
{cout << "Constructor2" << endl;i=val;
}void Sample::Display()
{cout << "i=" << i << endl;
}Sample::~Sample()
{cout << "Destructor" << endl;
}int main()
{Sample a, b(10);a.Display();b.Display();return 0;
}
Constructor1
Constructor2
i=0
i=10
Destructor
Destructor
10,设已经有A,B,C,D 4个类的定义,程序中A,B,C,D析构函数调用顺序为? ABDC(坏)
C c;
int main()
{A *pa=new A();B b;static D d;delete pa;return 0;
}
A B D C (坏,后创建的先销毁
1,堆对象,delete删除时
2,全局对象,整个程序结束时
3,静态对象,整个程序结束时
4,局部对象,程序离开局部对象的作用域时
11,定义一个学生类,其中有3个数据成员:学号、姓名、年龄,以及若干成员函数。同时编写main函数,使用这个类,实现对学生数据的复制、赋值与输出。
#include <iostream>
#include <string.h>
using std::cout;
using std::endl;class Student{
public:Student(int id,int age,const char* name):_id(id),_age(age),_name(new char[strlen(name)+1]()){strcpy(_name,name);}Student(const Student & s):_id(s._id),_age(s._age),_name(new char[strlen(s._name)+1]()){strcpy(_name,s._name);}Student & operator=(const Student & s){if(this!=&s){_id=s._id;_age=s._age;delete [] _name;_name=new char[strlen(s._name)]();strcpy(_name,s._name);}return *this;}~Student(){cout<<_name<<" ";if(_name){delete [] _name;_name=nullptr;cout<<"love xixi"<<endl;}}void printStudent(){cout<<_id<<"\t"<<_age<<"\t"<<_name<<endl;}
private:int _id;int _age;char* _name;
};
void test(){Student jia(1,21,"jiajia");jia.printStudent();Student kai(1,21,"kaixin");jia.printStudent();Student hui(kai);hui.printStudent();hui=jia;hui.printStudent();
}int main(void)
{test();return 0;
}
1 21 jiajia
1 21 jiajia
1 21 kaixin
1 21 jiajia
jiajia love xixi
kaixin love xixi
jiajia love xixi //只调用了三次析构函数喵 是我 en~~~?