设为首页 加入收藏

TOP

C++ Primer Plus的若干收获--(十二)
2015-07-20 18:01:13 来源: 作者: 【 】 浏览:3
Tags:Primer Plus 若干 收获 十二

期待已久的建模的日子终于来了,可是真的到了这一天有感觉少了点什么,少了点什么呢??对了,今天是我博客访问量突破1000的大日子,哈哈。不过我的目标可是在毕业之前访问量超过10000啊,嘻嘻。

本篇讲的内容不多,主要通过一个例子引出了类的特殊成员函数这个概念。然后主要讲解了在使用析构函数,默认构造函数和默认的复制构造函数遇到的问题,以及它们的主要用法。下篇将是其的姊妹篇,将会补充这篇的内容。

11.1 复习实例和静态类成员

这里我们先给出一个不太完整的类的示例,然后随着这个类的一点点完善来讲解类和动态内存分配

class StringBad
{
    
private:
    char* str;
    int len;
    static int num_strings;
public:
        StringBad(const char* s)
        {
            len=std::strlen(s);
            str=new char[len+1];
            std::strcpy(str,s);
            num_strings++;
            cout<
  
   在这里,我们通过讲解这个程序来复习一下之前讲过的知识
  

(1)首先,我们需要给num_strings初始化,但是我们发现在这个声明中没有,则我们需要这样一句

int StringBad::num_strings=0;

请注意,不能在类声明中初始化静态成员变量,这是因为在类的声明中描述了如何分配内存,单不分配内存。您可以使用这种格式来创建对象,从而分配和初始化内存。对于静态类成员,可以在声明之外使用单独的语句进行初始化,这是因为静态类成员是单独存储的,而不是对象的组成部分,注意在这里并没有使用static.

(2)对于private部分,它使用char指针来表示姓名。这意味着类声明没有为字符串本身分配存储空间,而是在构造函数中使用new来问字符串分配空间。

(3)在构造函数中使用new来分配内存时,必须在相应的析构函数中使用delete来释放内存。如果使用new【】来分配内存,则应使用delete【】来释放内存。

这里,我再给出一个此类的调试,以及调试所得的输出:

void callme1(StringBad&){cout<<"String passed by refference:\n";  cout<<"    \""<
  

   


   

这里在标记1处,callme2()按值传递headline2,结果表明是个严重的错误。首先,将headline2作为函数参数会调用析构函数(在这里,当callme2()函数调用结束时,会调用析构函数)。为什么引用是就不会调用析构函数呢?此时,原始字符串已经被删除,故无法识别,才会出现上述的结果。

这里再看一下标记2,因为自动存储对象被删除的顺序与创建顺序相反,所以最先删除的是三个对象是knots、sailor、sport。在删除sport时,Dollars变成了Doll8.对于sport,程序只使用它来初始化sailor,单这种操作修改了sport。剩下的两个对象就更不能识别了。

最后在看一下计数异常。因为每个对象呗构造和析构一次,因此调用够早的函数的次数应当与析构函数的调用次数相同。对象技术(num_strings)递减的次数比递增的次数多2,这证明使用了不将其递增的构造函数。下面我们着重来看这条代码。

StringBad sailor=sports;
StringBad sailor=StringBad(sports);//其等价于上式

StringBad(const StringBad &);//其构造函数的原型

当您使用一个对象去初始化另一个对象时,编译器将自动生成上述的构造函数,其被称为复制构造函数。

11.2 特殊的成员函数

StringBad类的问题是有特殊成员函数引起的。这些成员函数是自动定义的,就StringBad而言,这些函数的行为与其类的设计不符。具体的将,C++提供下面了成员函数

默认构造函数,如果没有定义构造函数默认析构函数,如果没有定义复制构造函数,如果没有定义赋值运算符,如果没有定义地址运算符,如果没有定义

这里我们主要讲解一下几点:

(1)默认构造函数

如果没有提供任何构造函数,C++将创建默认的构造函数。比如有一个Pig类

Pig::Pig() {  }


也就是说,编译器将提供一个不接受任何参数,也不执行任何操作的的构造函数,因为在创建对象时总会遇到构造函数

Pig pig;


如果你定义了构造函数,则C++将不会自动定义默认的构造函数了。如果你仍希望不显式的初始化,则必须显式的调用默认构造函数。其没有参数,但是可以用它来设置特定的值:

Pig::Pig()
{
  pig_ct=0;
  ...
}


(2)复制构造函数

复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的复制过程中。复制构造函数的原型为

class_name(const Class_name &);


(3)默认的复制构造函数的功能

默认的构造函数逐个复制非讲台成员(成员复制也成为浅复制),复制的是成员的值。下述语句中的两端代码是等效的

StringBad sailor=sports;


StringBad sailor;//与上面的代码等效
sailor.str=sports.str;
sailor.len=sports.len;


(4)何时调用复制的构造函数

新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。假设motto为StringBad对象,则在下面的声明中都将调用复制构造函数:

StringBad ditto(motto);
StringBad metoo=motto;
StringBad also=StringBad(motto);
StringBad* pStringBad=new StringBad(motto);


一看表都十二点了,哈哈,果然心情好,干什么事都有干劲啊,大家,晚安

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇POJ2001_Shortest Prefixes(字典.. 下一篇RMQ uva11235

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: