第12章类和动态内存分配
2015-09-20 21:41
225 查看
第12章类和动态内存分配 (1) class student { char name[40];//并不是每一个字符串都是40 //如果是一个对象数组,则浪费空间 }; 12.1 (1)静态成员在类声明中声明,在包含类方法的文件中初始化。初始化时使作用域运算符来指出静态成员所属的类。但如果静态成员是整形或枚举型const,则可以在类声明中初始化 初始化 : 类型 类名::变量名 = 初始化的值 (2)析构函数在定义对象的代码块执行完毕时调用 12.1.2特殊成员函数 (1)c++自动提供成员函数: [1]默认构造函数,如果没有定义构造函数 [2]默认析构函数,如果没有定义 [3]复制构造函数,如果没有定义 [4]赋值运算函数,如果没有定义 [5]地址运算符,如果没有定义 (2) #include<iostream> #include<string.h> using namespace std; class CMyString { public: static int m_nString;//创建对象的个数 private: int len; char *m_nStr; public : CMyString(const char *str) { m_nStr=new char [strlen(str)+1]; strcpy(m_nStr,str); m_nString++; } CMyString (const CMyString &myStr) { m_nString++; } ~CMyString() { --m_nString; delete []m_nStr; } friend ostream & operator <<(ostream &os, CMyString &Str); }; ostream & operator <<(ostream &os, CMyString &Str) { os<<Str.m_nStr<<endl; return os; } int CMyString::m_nString=0; int main() { CMyString str("hello word"); cout<<str; CMyString str1=str; cout<<CMyString::m_nString<<endl; return 0; } 如果类中包含这样的静态数据成员,即其值将在新对象被创建时发生变化,则应该提供一个显示复制构造函数来处理计数问题 (3)浅拷贝:得到的是两个指向同一个字符串的指针 深度复制:应当将复制字符串并将副本的地址赋给str成员, 而不仅仅是复制字符串地址,这样每个对象都有自己的字符串,而不是引用另一个对象的字符串。调用析构函数时都将释放不同的字符串,而不会试图去释放已经被释放的字符串。 StringBad::String Bad(const StringBad &st) { Num_strings++; len = st.len; str = new char =[len+1]; std::strcpy(str,st.str); } (4)解决赋值的问题: [1]由于目标对象可能引用了以前分配的数据,所以函数应使用delete[] 来释放这些数据 [2]函数应当避免将对象给自身;否则,给对象重新赋值前,释放内存操作可能删除对象的内容 [3]函数返回一个指向调用对象的引用 StringBad & StringBad::operator=(const StringBad &st) { if(this==&st) { return *this; } delete []str; len=str.len; str=new char[len+1]; std::strcpy(str,st.str); return *this; } (5) #include<iostream> #include<string.h> using namespace std; class CMyString { private: char *m_pStr; int len; public: CMyString()/*C++11中空指针nullpstr*/ { len = 0; m_pStr = new char [1]; m_pStr[0] = '\0'; } CMyString(const char *str) { len=strlen(str); m_pStr = new char [len+1]; strcpy(m_pStr,str); } const char & operator [](int index) const //对于const 对象只可以读 { cout<<"Const"<<endl; return m_pStr[index]; } char & operator [](int index)//读写常规的CMyString对象 { cout<<"No Const"<<endl; return m_pStr[index]; } friend ostream & operator<<(ostream &os,const CMyString &myString) ; }; ostream & operator <<(ostream &os, const CMyString &myString) { os<<myString.m_pStr; return os; } int main() { const CMyString str1("hello world"); cout<<str1<<endl; char c=str1[7]; cout<<c<<endl; cout<<str1[10]<<endl; CMyString str2 = "ni hao"; cout<<str2[1]<<endl; //str2[1]='d'; cout<<str2<<endl; return 0; } (6) #include<iostream> #include<string.h> using namespace std; class String { private: char *str; int len; static int num_strings; public: static const int CINLIM = 80; String (const char *s);//constructer String(); String(const String &); ~String(); int length() const { return len; } public: String &operator = (const String &); String &operator = (const char *); char &operator [] (int i); const char & operator [](int i) const; public: friend bool operator<(const String &st,const String &st2); friend bool operator>(const String &st,const String &st2); friend bool operator==(const String &st,const String &st2); friend ostream & operator <<(ostream &os,const String &st); friend istream & operator >>(istream &is,const String &st); public : static int HowMany() { return num_strings;} }; int String::num_strings = 0; String::String(const char *s) { len=strlen(s); str = new char [len + 1]; strcpy(str,s); num_strings++; } String::String() { len = 4; str = new char [1]; str[0] = '\0'; num_strings++; } String::String(const String &st) { len=st.len; str=new char[len+1]; strcpy(str,st.str); num_strings++; } String::~String() { --num_strings; delete []str; } String & String::operator=(const String &st) { if(this==&st) { return *this; } delete []str; len=st.len; str=new char [len+1]; strcpy(str,st.str); return *this; } String & String::operator=(const char *s) { delete []str; len=strlen(s); str = new char [len+1]; strcpy(str,s); return *this; } char & String::operator[](int i) { return str[i]; } const char & String::operator [](int i)const { return str[i]; } bool operator<(const String &st1,const String &st2) { return (strcmp(st1.str,st2.str)<0); } bool operator>(const String &st1,const String &st2) { return st2<st1; } bool operator==(const String &st1,const String &st2) { return (strcmp(st1.str,st2.str)==0); } ostream & operator <<(ostream &os,const String &st) { os<< st.str; return os; } istream & operator >>(istream &is,String &st) { char temp[String::CINLIM]; is.get(temp,String::CINLIM); if(is) { st=temp; while(is&&is.get()!='\n') continue; } return is; } int main() { String str; cin>>str; cout<<str<<endl; cout<<str.length()<<endl; return 0; } 12.4有关返回对象的说名 (1)如果方法或函数要返回局部对象,则应返回对象,而不是指向对象的引用。在这种情况下,将使用复制构造函数来生成返回的•对象。如果方法或函数要返回一个没有公有复制构造函数 的类(如ostream类)的对象,它必须返回一个指向这种对象的引用。 12.5.1 (1)析构函数的调用: [1]:如果对象是动态变量,则当执行完定义该对象的程序块时,将调用该对象的析构函数 [2]静态变量(外部,静态,静态外部或来自命名空间),则在程序结束是将调用对象的析构函数 [3]如果对象是用new创建的,则仅当使用delete删除对象是,其析构函数才会被调用 12.5.2 (1)析构函数可以自己调用 12.7 (1)成员初始化列表: [1]这种格式只能用于构造函数 [2]必须使用这种格式来初始化非静态const数据成员 [3]必须用这种格式初始化引用数据成员
相关文章推荐
- PHP 7革新与性能优化
- Linux基础入门第三节(修改)
- Oracle 11g EM安全证书问题无法访问的解决办法
- AngularJS + RequireJS
- 深入理解IntentService
- Service kongleifeng深究
- 第 十 天 : 添 加 硬 盘 和 分 区 挂 载 等
- 大三第一学期实验报告
- 汇编总结:lea指令
- MVC5 + EF6 + Bootstrap3 (11) 排序、搜索、分页
- ios-新浪微博开发-18-(授权存储账号信息)用归档实现
- hdoj 4549 M斐波那契数列 【矩阵快速幂 + 费马小定理 + 快速幂】
- MySQL中group_concat函数,用符号连接查询分组里字段值
- 实验一 Linux初步认识
- 对Git的认识
- 从c到c++<一>
- Javascript - code snippet - function 1
- AngularJS - 使用RequireJS还是Browserify?
- 项目开发的步骤
- metex实现读写锁的思考