您的位置:首页 > 其它

第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]必须用这种格式初始化引用数据成员
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: