第12章类和动态内存分配

第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]必须用这种格式初始化引用数据成员

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值