第12章——类和动态分配内存

 

使用new操作符可以在程序运行时分配所需的内存

l         动态内存和类

eg:

#include <iostream>

#ifndef STRNGBAD_H_

#define STRNGBAD_H_

class StringBad

{

private:

    char * str;                // pointer to string

    int len;                   // length of string

    static int num_strings;    // number of objects

public:

    StringBad(const char * s); // constructor

    StringBad();               // default constructor

    ~StringBad();              // destructor

// friend function

       friend std::ostream & operator<<(std::ostream & os,

                       const StringBad & st);

};

#endif

说明:类使用了char指针和静态数据成员。

 

以下是类方法

#include <cstring>                    // string.h for some

#include "strngbad.h"

using std::cout;

 

// initializing static class member

int StringBad::num_strings = 0;

 

// class methods

 

// construct StringBad from C string

StringBad::StringBad(const char * s)

{

    len = std::strlen(s);                  // set size

    str = new char[len + 1];          // allot storage

    std::strcpy(str, s);                   // initialize pointer

    num_strings++;                    // set object count

    cout << num_strings << ": \"" << str

         << "\" object created\n";    // For Your Information

}

 

StringBad::StringBad()                // default constructor

{

    len = 4;

    str = new char[4];

    std::strcpy(str, "C++");               // default string

    num_strings++;

    cout << num_strings << ": \"" << str

         << "\" default object created\n";  // FYI

}

 

StringBad::~StringBad()               // necessary destructor

{

    cout << "\"" << str << "\" object deleted, ";    // FYI

    --num_strings;                    // required

    cout << num_strings << " left\n"; // FYI

    delete [] str;                    // required

}

 

std::ostream & operator<<(std::ostream & os, const StringBad & st)

{

    os << st.str;

    return os;

}

 

#include <iostream>

using std::cout;

 

#include "strngbad.h"

 

void callme1(StringBad &);  // pass by reference

void callme2(StringBad);    // pass by value

 

 

使用类实例(红色部分为解释或相应的输出结果)

int main()

{

    using std::endl;

StringBad headline1("Celery Stalks at Midnight");

此处输出:

1:”Celery Stalks at Midnight” object created

StringBad headline2("Lettuce Prey");

2:” Lettuce Prey” object created

StringBad sports("Spinach Leaves Bowl for Dollars");

3:” Spinach Leaves Bowl for Dollars” object created

cout << "headline1: " << headline1 << endl;

此处重载了”<<”符号,输出结果为

headline1: Celery Stalks at Midnight

cout << "headline2: " << headline2 << endl;

headlin2: Lettuce Prey

cout << "sports: " << sports << endl;

sports: Spinach Leaves Bowl for Dollars

callme1(headline1);

String passed by reference:

       “Celery Stalks at Midnight”

cout << "headline1: " << headline1 << endl;

headline1: Celery Stalks at Midnight

callme2(headline2);

String passed by value:

       “Lettuce Prey”

“Lettuce Prey”deleted, 2 left

此处打印“Lettuce Prey”deleted, 2 left是调用析构函数的结果。调用析构函数的原因是headline2的参数赋给callme2()函数的形参sb时,会调用复制构造函数。函数调用后,要删除sb,此时便会调用析构函数。

cout << "headline2: " << headline2 << endl;

headline2:D 0

此处headline2:后出现的是乱码。这是因为callme2()调用引起的复制构造函数的调用。因为默认情况复制构造函数只执行浅复制。这导致headline2和sb类的char指针指向同一个地址。当调用析构函数后,删除了sb,实际上也删除了headline2中char指针。

cout << "Initialize one object to another:\n";       

Initialize one object to another:

StringBad sailor = sports;       

说明:此处亦调用了复制构造函数,初始化类有可能调用了赋值操作符,也有可能没有。此处实现没有调用赋值操作符,因为如果调用了的话,复制构造函数会创建一个中间临时对象,而删除临时对象后会导致析构函数调用。

cout << "sailor: " << sailor << endl;

sailor: Spinach Leaves Bowl for Dollars

cout << "Assign one object to another:\n";

Assign one object to another:

StringBad knot;

3:”C++” default object created

knot = headline1;

说明,此处调用的是默认的赋值操作符

cout << "knot: " << knot << endl; 

knot: Celery Stalks at Midnight

    cout << "End of main()\n";

    End of main()

    return 0;

}

“Celery Stalks at Midnight” object deleted,2 left

“Spinach leaves Bowl for Dollars” object deleted,1 left

“Spinach leaves Bowl for Doll8 ” object deleted,0 left

“@g” object deleted,-1 left

“-|” object deleted,-2 left

 

最后两个异常的原因和上面介绍的一样,复制构造函数和默认的赋值操作符都是浅复制。使指针在复制前后都是指向同一个地方。

 

void callme1(StringBad & rsb)

{

    cout << "String passed by reference:\n";

    cout << "    \"" << rsb << "\"\n";

}

 

void callme2(StringBad sb)

{

    cout << "String passed by value:\n";

    cout << "    \"" << sb << "\"\n";

}

 

C++为类构造函数提供了一种可用来初始化数据成员的特殊句法。

eg:queue(int qs):qsize(qs),items(0),front(NULL),rear(NULL){}

如果数据是非静态const成员或引用,则必须采用这种格式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值