| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3201 人关注过本帖, 6 人收藏
标题:C++学习笔记,已结束
取消只看楼主 加入收藏
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
明天把“类”这一章的笔记写完,就跟我的学习进度同步了。最近状态很差,上课都是在画重点,没办法看书熬课上时间了  进度也变慢了,原先一天20页,这星期总共看了20页,看完16章就可以了。下星期开始复习,计划一周更新一章。25号结束整个学习笔记。
谢谢大家的关注。
程序代码:
2011.6.1
第12章    类
    成员可以是数据、函数或类型别名。
    构造函数初始化列表跟在构造函数的形参表之后,并以冒号开头。
    在类内部,声明成员函数是必需的,而定义成员函数则是可选的。
        类内部定义的函数默认为inline。
        成员函数有一个附加的隐含实参——this指针。
    const必须同时出现在声明和定义中。
    
    类背后蕴含的基本思想是数据抽象和封装。
    封装是一项将低层次的元素组合起来形成新的、高层次实体的技术。
    一个访问标号可以出现的次数通常是没有限制的。
    数据抽象和封装的两个重要有点:
        避免类内部出现无意的、可能破坏对象状态的用户级错误。
        随时间推移可以根据需求改变或缺陷报告来完善类实现,而无须改变用户级代码。
        
    类可以定义自己的局部类型名字,将这个类型设为public,就允许用户使用这个名字。
    成员函数只能重载本类的其他成员函数。
    不在类定义体内定义的inline成员函数,其定义通常应放在有类定义的同一头文件中。
        对于不完全类型,不能定义该类型的对象,只能用于定义指向该类型的指针及引用,或者用于声明使用该类型作为形参类型或返回类型的函数。
    定义类型时不进行存储分配。
    因为在类定义之后可以接一个对象定义列表。定义必须以分号结束。
    
    成员函数不能定义this形参。
    当我们需要将一个对象作为整体引用而不是引用对象的一个成员时,需要显式引用this。
    const成员函数只能返回*this作为一个const引用。
    
    可变数据成员永远都不能为const,const成员函数可以改变mutable成员。
    
    定义类型的成员,如Screen::index(称为完全限定名),使用作用域操作符来访问。
    返回类型出现在成员名字前面,如果返回类型使用由类定义的类型,则必须使用完全限定名。
    在C++程序中,所有名字必须在使用之前声明。
    如果类作用域中使用的名字不能确定为类成员名,则在包含该类或成员定义的作用域中查找,以便找到该名字的声明。
    一旦一个名字被用作类姓名,该名字就不能被重复定义。
    尽管类的成员被屏蔽了,但仍然可以通过用类名来限定成员名或显式使用this指针来使用它。
    尽管全局对象被屏蔽了,但通过用全局作用域确定操作符(::)来限定名字,仍然可以访问。
2011-06-01 22:21
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
to aikongfu:借你吉言咯。
to wyfeng2010:加油!
程序代码:
2011.6.2
    只要创建类类型的新对象,都要执行构造函数。
    构造函数不能声明为const。
    创建类类型的const对象时,运行一个普通构造函数来初始化该const对象。
    构造函数可以定义在类的内部或外部。
    构造函数初始化式只在构造函数的定义中而不是声明中指定。
    构造函数分两个阶段执行:(1)初始化阶段 (2)普通的计算阶段
        计算阶段由构造函数体中的所有语句组成。
        类类型的数据成员总是在初始化阶段初始化。
        初始化发生在计算阶段开始之前。
    有些成员必须在构造函数初始化列表中进行初始化。对于这样的成员,在构造函数函数体中对它们赋值不起作用,没有默认构造函数的类类型成员,以及const或引用类型成员,都必须在构造函数初始化列表中进行初始化。
        初始化const或引用类型数据成员的唯一机会是在构造函数初始化列表中。
    不指定初始化执行的次序,成员被初始化的次序就是定义成员的次序。
        按照与成员声明一致的次序编写构造函数初始化列表是个好主意。
        尽可能避免使用成员来初始化其他成员。
    
    一个类哪怕只定义了一个构造函数,编译器也不会再生成默认构造函数。
    如果每个构造函数将每个成员设置为明确的已知状态,则成员函数可以区分空对象和具有实际值的对象。
    如果定义了其他构造函数,则提供一个默认构造函数几乎总是对的。
    初级C++程序员常犯的一个错误:Sales_item myobj();    这是函数声明,不是一个对象。
        正确做法:Sales_item myobj;    或者    Sales_item myobj = Sales_item();
    
    可以通过将构造函数声明为explicit,来防止在需要隐式转换的上下文中使用构造函数。
        explicit关键字只能用于类内部的构造函数声明上,类的定义体外部所做的定义上不再重复。
    任何构造函数都可以用来显式地创建临时对象。
    通常,除非有明显的理由想要定义隐式转换,否则,单形参构造函数应该为explicit。
    
    友元(friend)机制允许一个类将对其非公有成员的访问权授予指定的函数或类。
        只能出现在类定义的内部。
        一般在开始或结尾。
    友元可以是普通的非成员函数,或前面定义的其他类的成员函数或整个类。
    必须先定义包含成员函数的类,才能将成员函数设为友元。另一方面,不必预先声明类和非成员函数来将它们设为友元。    现在看怎么这么饶,大概意思应该是对于友元是成员函数,应该先定义包含该成员函数的类;友元是类和非成员函数,则不必预先声明。
    类必须将重载函数集中每一个希望设为友元的函数都声明为友元。
    
    类可以定义类静态成员。
    static数据成员独立于该类的任意对象而存在,它是与类关联的对象。
    static成员函数没有this形参。
        它可以直接访问所属类的static成员,但不能直接使用非static成员。
    static成员是类的组成部分但不是任何对象的组成部分。
    static成员函数不能被声明为const或虚函数。
    static数据成员必须在类定义体的外部定义。
        static成员在定义时进行初始化。
        将static数据成员的定义放在包含类的非内联成员函数定义的文件中。
    一旦成员名出现,static成员的定义就是在类作用域中。
    static关键字只能用于类定义体内部的声明中,定义不能标示为static。
    一般而言,类的static成员,像普通数据成员一样,不能在类的定义体中初始化。
        例外是const static数据成员可以在类的定义体内初始化。
        该数据成员仍必须在类的定义体之外进行定义,不必再指定初值。
        
    通过将类的实现所用到的数据和函数设置为private来封装类。
2011-06-02 23:39
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
to test_l:有志者事竟成
程序代码:
2011.6.12
第13章    复制控制
    如果没有显式定义复制构造函数或赋值操作符,编译器(通常)会为我们定义。
    复制构造函数具有单个形参,该形参(常用const修饰)是对该类类型的引用。    复制构造函数最主要的识别特征!
        当将该类型的对象传递给函数或从函数返回该类型的对象时,将隐式使用复制构造函数。
    赋值操作符可以通过指定不同类型的右操作数而重载。
    编译器自动实现复制控制(复制构造函数、赋值操作符和析构函数),也可以定义自己的版本。
    当类具有指针成员,需要类定义自己的复制控制成员。
    
    复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将临时对象复制到正在创建的对象。
    vector<string> svec(5);    容器这种构造方式使用了默认构造函数和复制构造函数。
    对于类类型数组,如果希望不指定实参或指定多个实参,就需要使用完整的构造函数语法。
    
    编译器在即使我们定义了其他构造函数,也会合成复制构造函数。
    复制数组时合成复制构造函数将复制数组的每一个元素。
    有些类必须对复制对象时发生的事情加以控制:1.类经常有一个数据成员是指针;2.一些类在创建新对象时必须做一些特定工作。
    
    有些类需要完全禁止复制,类必须显式声明其复制构造函数为private。
    如果连友元和成员中的复制也禁止,则声明private但不对其定义。
    
    重载操作符是一些函数,名字为operator后跟着所定义的操作符的符号。
    当操作符为成员函数时,它的第一个操作数隐式绑定到this指针。
    内置类型的赋值运算返回对右操作数的引用。 赋值操作符的返回类型应该与内置类型赋值运算返回的类型相同。
    合成赋值操作符返回*this,对左操作数对象的引用。
    
    撤销类对象时会自动调用析构函数。
        容器中的元素总是按逆序撤销。
    三法则:如果类需要析构函数,则它也需要赋值操作符和复制构造函数。    这是一个经验法则。
    合成析构函数并不删除指针成员所指向的对象。
    不能重载析构函数。
    即使编写了析构函数,合成析构函数仍然运行。
    
    中间的消息处理示例跳过,管理指针成员看的迷迷糊糊,大概意思明白了,当时看这一章时,感受十分不好,现在写笔记回头看,思路清晰了许多,也不再赘述,是一种方法。    
    最后以书上的一句话结束本章:定义复制控制函数最为困难的部分通常在于认识到它们的必要性。
    
第14章    重载操作符与转换
    保留字operator后接需定义的操作符符号。
    重载操作符具有返回类型和形参表。
    重载操作符的形参数目(包括成员函数的隐式this)与操作符的操作数数目相同。
        函数操作符( operator() )可以接受任意数目的操作数。
    重载操作符必须具有一个类类型或枚举类型操作数。
        用于内置类型的操作符,其含义不能改变。
        不能为任何内置类型定义额外的新的操作符。
    操作符的优先级、结合性或操作数数目不能改变。
    +,-,*和&取决于操作数数目。
    函数调用操作符之外,重载操作符时使用默认实参是非法的。
    重载操作符并不保证操作数的求值顺序。
    作为类成员的重载函数,隐含的this形参,限定为第一个操作数。
    操作符定义为非成员函数时,通常必须将它们设置为所操作类的友元。
    
    如果重新定义&&和||,将失去操作符的短路求值特征。
    重载逗号、取地址、逻辑与、逻辑或等操作符通常不是好做法。
    当一个重载操作符的含义不明显时,给操作取一个名字更好。对于很少用的操作,使用命名函数通常也比用操作符更好。
    复合赋值操作符通常应定义为类的成员。
    自增、自减和解引用应定义为类成员。
    对称的操作符,如算术操作符、相等操作符、关系操作符和位操作符,最好定义为普通非成员函数。
    
    输出操作符<<返回类型是一个ostream引用。
    一般而言,输出操作符应输出对象的内容,进行最小限度的格式化,它们不应该输出换行符。让用户自己控制输出细节。
    必须使输出或输入操作符称为非成员操作符。
    输入操作符必须处理错误和文件结束的可能性。
    输入期间的错误:
        (1)任何读操作都可能因为提供的值不正确而失败。这次的读入以及流的后续使用都将失败。
        (2)任何读入都可能碰到输入流中的文件结束或其他一些错误。
    设计输入操作符时,如果可能,要确定错误恢复措施,这很重要。
    通常错误最好留给IO标准库自己来指出。
    
    为了与内置操作符保持一致,加法返回一个右值,而不是一个引用。    这里总结一下:对于重载操作符,要遵循标准库定义的习惯,保持使用习惯上的统一。
    相等和不等操作符一般应该相互联系起来定义,让一个操作符完成比较对象的实际工作,而另一个操作符只是调用前者。
    赋值操作符必须定义为成员函数,且必须返回对*this的引用。
    一般而言,赋值操作符与复合赋值操作符应返回左操作数的引用。
    下标操作符必须定义为类成员函数。
        一般需要定义两个版本,一个为非const成员并返回引用,另一个为const成员并返回const引用。
        这里讨论一下书上的例子:
            int &operator[] (const size_t);
            const int &operator[] (const size_t) const;
                重载的判决因素应该有该成员函数是否为const。
    箭头操作符必须定义为类成员函数。
        必须返回指向类类型的指针,或者返回定义了自己的箭头操作符的类类型对象。
    解引用操作符不要求定义为成员。
    自增/自减操作符的前缀与后缀的区别方法:
        后缀式操作符函数接受一个额外的(无用的)int型形参。    使用后缀式操作符时,编译器提供0作为这个形参的实参。
    为了与内置类型一致,前缀式操作符应返回被增量或减量对象的引用,后缀式操作符应返回旧值,且应作为值返回。
        一般而言,最好前缀式和后缀式都定义。
    函数调用操作符必须声明为成员函数。一个类可以定义函数调用操作符的多个版本,由形参的数目或类型加以区别。
        定义了调用操作符的类,其对象常称为函数对象,即它们是行为类似函数的对象。
        函数对象经常用作通用算法的实参。
    标准库函数对象类型在functional头文件中定义。
        每个标准库函数对象类表示一个操作符。
        给出一个使用例子:
            sort(svec.begin(), svec.end(), greater<string>);
        函数适配器种类:
            绑定器(binder),它通过将一个操作数绑定到给定值而将二元函数对象转换为一元函数对象。
                bind1st, bind2nd        名字表现出绑定的实参位置。
            求反器(negator),它将谓词函数对象的真值求反。
                not1, not2    名字表现出对几元函数对象的真值求反。
    
    一个类可以定义自己的转换,应用于其类类型对象。
    转换操作符是一种特殊的类成员函数。
        operator type();
        转换函数必须是成员函数,不能指定返回类型,并且形参表必须为空。
        转换函数一般不应该改变被转换的对象。因此,转换操作符通常应定义为const成员。
    类类型转换之后不能再跟另一个类类型转换。
    
    之后内容跳过。
2011-06-12 17:17
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
开始考试,我都还没复习。我不想最后一学期挂科啊~~~~~~  先停止C++。25号之后,再做计较

to bad_boy:数据结构的链表么? 数据结构书上都讲得很详细吧?我菜鸟。放过我
to plp313131:加油~不过现在别学我 - -# 连课本都看不进去。。
to 一点温柔:像一点温柔童鞋看齐!
收到的鲜花
2011-06-17 22:47
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
程序代码:
2011.7.3
第15章    面向对象编程
    面向对象编程(Object-oriented programmingm OOP)基于三个基本概念:数据抽象、继承和动态绑定。
    多态性,通过继承而相关联的类型为多态类型,是因为在许多情况下可以互换地使用派生类型或基类型的“许多形态”。
    在C++中,多态性仅用于通过继承而相关联的类型的引用或指针。
    在C++中,基类必须指出希望派生类重定义哪些函数,定义为virtual的函数是基类期待派生类重新定义的,基类希望派生类继承的函数不能定义为虚函数。
    在C++中,通过基类的引用(或指针)调用虚函数时,发生动态绑定。
    继承层次的根类一般都要定义虚析构函数即可。
    在非虚函数的调用在编译时确定。除了构造函数之外,任意非static成员函数都可以是虚函数,保留字virtual不能用在类定义体外部出现的函数定义上。
    protected成员可以被派生类对象访问但不能被该类型的普通用户访问。
    派生类只能通过派生类对象访问其基类的protected成员,派生类对其基类类型对象的protected成员没有特殊访问权限。
        提供给派生类型的接口是protected成员和public成员的组合。
    类派生列表指定了一个或多个基类。
        访问标号决定了对继承成员的(最大)访问权限。        这句话自己添加的不是很确切,主要是指继承成员的访问权限等于或严格于派生类的访问标号、
            如果想要继承基类的接口,则应该进行public派生。        经常见到的也是这种派生方式。
    派生类一般会重定义所继承的虚函数。
        如果派生类没有重定义,则使用基类中定义的版本。
    派生类必须对想要重定义的每个继承成员进行声明。
        派生类中虚函数的声明必须与基类中的定义方式完全匹配。    一个例外:返回对基类型的引用(或指针)的虚函数,派生类中的虚函数可以返回基类函数所返回类型的派生类的引用(或指针)。
        派生类重定义虚函数时,可以使用virtual,但不是必须这样做。
    
    已定义的类才可以用作基类。
        暗示着不可能从类自身派生出一个类。
    基类本身可以是一个派生类。
    如果需要声明(但并不实现)一个派生类,则声明包含类名但不包含派生列表。
    可将基类类型的引用绑定到派生类对象的基类部分,指针也是如此。        这里注意是基类的引用或指针可以绑定到派生类上,反之则不行。
    任何可以在基类对象上执行的操作也可以通过派生类对象使用。
    引用和指针的静态类型与动态类型可以不同,这是C++用以支持多态性的基石。        静态类型:static type, 在编译时可知的引用类型或指针类型。        动态类型:dynamic type, 指针或引用绑定的对象的类型,这是仅在运行时可知的)。
        如果调用非虚函数,则无论实际对象是什么类型,都执行基类类型所定义的函数。
        只有通过引用或指针调用,虚函数才在运行时确定。
    非虚函数总是在编译时根据调用该函数的对象、引用或指针的类型而确定。
    只有成员函数中的代码才应该使用作用域操作符覆盖虚函数机制。
        最常见的理由是为了派生类虚函数调用基类的版本。
    通过基类的引用或指针调用虚函数时,默认实参为在基类虚函数声明中指定的值,如果通过派生类的指针或引用调用虚函数,则默认实参是在派生类的版本中声明的值。
    
    派生类可以进一步限制但不能放松对所继承的成员的访问。
    无论派生列表中是什么访问标号,所有继承Base的类对Base中的成员具有相同的访问。
    在继承层次的设计中,有一个重要概念:是一种(Is A) 有一个(Has A)
    为了使size在Derived中成为public,可以在Derived的public部分增加一个using声明:using Base::size; , 从而恢复继承成员的访问级别。
    私有继承相当罕见,所以如果确实需要,显式指定可避免误解。    struct派生则默认为public, class派生则默认为private。
    
    友元可以访问类的private和protected数据。
        友元关系不能继承。如果基类被授予友元关系,则只有基类具有特殊访问权限。
    
    每个static成员只有一个实例。
    确定派生类到基类转换的可访问性取决于在派生类的派生列表中指定的访问标号。
    从基类到派生类的自动转换是不存在的。        如果确定可以,需要使用static_case强制转换。
    
    构造函数和复制控制成员不能继承。
    派生类构造函数的初始化列表只能初始化派生类的成员,不能直接初始化继承成员。
        可以将基类包含在构造函数初始化列表中间接初始化。
        class Bulk_item : public Item_base {
        public:
            Bulk_item(const std::string& book, double sales_price, 
                                std::size_t qty = , double disc_rate = 0.0) :
                                Item_base(book, sales_price),
                                min_qty(qty), discount(disc_rate) { }
        };
    一个类只能初始化自己的直接基类。        直接基类就是在派生列表中指定的类。
    派生类应通过使用基类构造函数尊重基类的初始化意图。
    
    具有指针成员的类一般需要定义自己的复制控制来管理成员。
    派生类析构函数不负责撤销基类对象的成员。
    基类中的析构函数必须是虚函数。
        即使析构函数没有工作要做,继承层次的根类也应该定义一个虚析构函数。
        强调之前,虚函数必须在基类和派生类中具有相同的形参。
    
    在继承情况下,派生类的作用域嵌套在基类作用域中。
    与基类成员同名的派生类成员将屏蔽对基类成员的直接访问。
        可以使用作用域操作符来访问被屏蔽的基类成员。
        设计派生类时,只要可能,最好避免与基类成员的名字冲突。
    在派生类作用域中派生类成员屏蔽基类成员,即使函数原型不同,基类成员也会被屏蔽。
    
    成员函数(无论虚还是非虚)可以重载。
        如果派生类重定义了重载函数,则通过派生类型只能访问派生类中重定义的那些成员。
        派生类不用重定义所继承的每一个基类版本,可以为重载成员提供using声明,一个using声明只能指定一个名字。
    通过基类类型的引用或指针调用函数时,编译器将在基类中查找该函数而忽略派生类。
    
    在函数形参表后面写上=0以指定纯虚函数。
        含有(或继承)一个或多个纯虚函数的类是抽象基类(Abstract base class)。
        不能创建抽象类型的对象。
        
    后面关于指针或引用管理的内容跳过。
    
第16章    模板与泛型编程
    这一章之所以阅读的主要原因在于看一位大牛的网站,他写的数据结构学习笔记,一直使用template的东西,简单阅读这一章,做到可以看懂代码即可,所以仅做了解。
    
    泛型编程就是以独立于任何特定类型的方式编写代码。
    模板是泛型编程的基础。
    函数模板是一个独立于类型的函数。
        template <typename T>
        int compare(const T &v1, const T &v2)
        {
            if (v1 < v2) return -1;
            if (v2 < v1) return 1;
            return 0;
        }
    inline函数模板,需要注意inline的位置:
        template <typename T> inline T min(const T&, const T&);
    
    书上16.1.2中,又一次提醒了关于重载条件的复习,详见P378.
    
    模板形参遵循常规名字屏蔽规则。与全局作用域中声明的对象、函数或类型同名的模板形参会屏蔽全局名字。
    每个非类型形参前面必须带上类型名字,省略关键字或类型说明符是错误的:
        template <typename T, U> T calc (const T&, const U&);
        改正为:template <typename T, typename U> T calc (const T&, const U&);
    typename显式指明一个名字是一个类型。所以在类型之前指定typename没有害处。
    在调用函数时非类型形参将用值代替,值的类型在模板形参表中指定。
        这里书上例子,很能说明问题:
            template <class T, size_t N> void array_init(T (&parm)[N])
            {
                for (size_t i = 0; i != N; ++i) {
                    parm[i] = 0;
                }
            }
            
            编译器从数组实参计算非类型形参的值:
            int x[42];
            double y[10];
            array_init(x);    // 实例化为array_init(int(&)[42])                            因为后面不再继续写了,所以这里提一下实例化的概念:产生模板的特定类型实例的过程称为实例化。
            array_init(y);    // 实例化为array_init(double(&)[10])
            对模板的非类型形参而言,求值结果相同的表达式将认为是等价的。调用的是相同的实例——array_init<int, 42>:
            int x[42];
            const int sz = 40;
            int y[sz + 2];
            array_init(x);
            array_init(y);
    
    编写泛型代码的两个重要原则:
        模板的形参是const引用。
        函数体中的测试只用<比较。        在本章笔记开头的代码就体现了这种优势。
            详细的原因,参见P534-P535
2011-07-03 17:31
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
本次对C++的正式初探算是告一段落。离真正掌握还差的很远,希望自己可以坚持不懈!
另外谢谢您的关注。
祝我们好运~
2011-07-03 17:34
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
to 玩出来的代码:您说的对我很有帮助。   我也曾经拿起过一些数据结构的书本进行学习,但是在一些内容上存在障碍,所以也不是特别积极。 正准备打算拜读Weiss的大作,不过又想想,还是踏实点,先系统学习下离散数学吧。 我这人比较注重理解,不喜欢记忆,也不是很赞同有人说理解了自然就记住了。这个问题取决了一些个人其他的因素,所以我还是比较尊重自己,learning by doing。如果我能够找到一些我想要真正实现的东西,我相信自然这些枯燥的东西会立刻容光散发的。   
    同样我想多说点的,编程在我的理解还是以解决自己需求为主要目的才能够真正给我带来乐趣。迄今为止,可以说编程让我感到唯一的愉快体验就是打麻将没有色子,简单地用个伪随机数来仿真,正像MIT的公开课程《计算机科学及编程导论》开篇引导学生的那样。我想学习编程,首先需要想清楚到底想用编程干什么?这也是我现在仍然在思考的问题,它可能会浪费一些时间,或者让自己有点不知所措,但是这个问题会伴随自己的编程生命,也是编程的主要理由和动力。
    谢谢您的指教,同样很巧,我们是老乡。
to specilize:呵呵~一起加油
2011-07-03 23:27
naruto01
Rank: 4
等 级:业余侠客
帖 子:103
专家分:280
注 册:2011-5-23
收藏
得分:0 
以下是引用naruto01在2011-5-28 01:26:17的发言:

现在已经看到第13章 复制控制。开始感觉比较吃力,希望自己可以坚持住。  在407页13.1.2上面一句,按照我的理解书上错了。网上查找资料,也没有提及。我的分析如下:
Sales_item item = string("9-999-99999-9");
 
Sales_item类有一构造函数:Sales_item(const string&)
如果这个构造函数被定义为explicit,那么上面语句的构造函数就不是显式的,应该初始化失败。对吧?  
  
书中代码注释是:This initialization is okay only if the Sales_item(const string&) constructor is not explocot
但是下面中文翻译出:如果构造函数是显式的,则初始化失败;如果构造函数不是显式的,则初始化成功。
  
希望有哪位朋友可以指点一下。
欢迎各位朋友对我学习中的一些错误提出批评和指导。非常感谢你们的关注!   
另外补充关于这个笔记的说明:我已经比较熟悉C,也之前看过一些国内的C++资料,大概也知道继承、重载等的概念,并且算是略读这本书,希望对C++有个权威、系统的了解。如果你感觉有点过于简略,那么也开始你的学习笔记之旅吧!
2011.5.27
第八章    标准IO库
    当一个类继承另一个类时,这两个类通常可以使用相同的操作。
    如果函数有基类类型的引用形参时,可以给函数传递其派生类类型的对象。
    wchar_t类型的标准输入对象是wcin;标准输出是wcout;而标准错误是wcerr。
    IO对象不可复制或赋值。
        只有支持复制的元素类型可以存储在vector或其他容器类型里。
        形参或返回类型不能为流类型。    如果想传递或返回IO对象,则必须传递或返回指向该对象的指针或引用。
    8.2.2给出代码中while(cin >> ival, !cin.eof())    解释下逗号操作符的求解过程:首先计算它的每一个操作数,然后返回最右边操作数作为整个操作的结果。
    flush操纵符不添加任何字符刷新流。 ends操纵符插入null。    endl输出一个换行符。
     
        如果程序崩溃,则不会刷新缓冲区,所以使用endl是个良好的习惯。
    使用tie函数可以将输入流和输出流绑在一起,任何读输入流的尝试都将首先刷新其输出流关联的缓冲区。
        例如cin.tie(&cout); ostream *old_tie = cin.tie(); cin.tie(0);
    IO标准库使用C风格字符串作为文件名。
        在尝试打开新文件之前,必须先关闭当前的文件流。
        如果遇到文件结束符或其他错误,将设置流的内部状态,以便之后不允许再对该流做读写操作。即使关闭流也不能改变流对象的内部状态。而调用clear后,就像重新创建了该对象。
        ifstream infile;
        ofstream outfile;
        infile.open("in");
        outfile.open("out");
        //通常检查打开是否成功,是个好习惯
        if(!infile && !outfile) {
            cerr << "error: unable to open input or output file: " << endl;
            return -1;
        }
         
        infile.close();    //关闭文件流
        infile.clear();    //重置流状态
        infile.open("next");
         
    以binary模式打开的流则将文件以字节序列的形式处理,而不解释流中的字符。
    以out模式打开的文件会被清空。如果要保存文件中已存在的数据,唯一方法是显示地指定app模式打开。
    ofstream outfile("file", ofstream::app);
     
    stringstream提供的转换或格式化:
        该对象的一个常见用法是,需要在多种数据类型之间实现自动格式化时使用该类类型。
        int val1 = 512, val2 = 1024;
        ostringstream format_message;
        //format_message内容:val1: 512\nval2: 1024\n
        format_message << "val1: " << val1 << "\n"
                                     << "val2: " << val2 << "\n";
        //自动将数值型数据的字符表示方式转换为相应的算术值
        istringstream input_istring(format_message.str());
        string dump;
        input_istring >> dump >> val1 >> dump >> val2;    //一般情况下,使用输入操作符读string时,空白符将会忽略(这里补充下空白符的概念:空格、制表符、垂直制表符、回车符、换行符和进纸符)
        

回头看这个问题,当时应该是被绕晕了。  没有问题~  在此回复一下
2011-10-13 00:24
快速回复:C++学习笔记,已结束
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019913 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved