
C++ Primer
文章平均质量分 50
Web客栈
这个作者很懒,什么都没留下…
展开
-
类的成员变量初始化的注意点
对于一个类的成员变量的初始化有很多的方式,其中一个方式的在该类的构造函数体中进行初始化。情况下面的例1:#include using namespace std;class rectangle{public: rectangle(){length = 3;width = 4;} //在构造函数体内进行赋值 int area() const{return length*wi原创 2013-06-08 22:12:02 · 458 阅读 · 0 评论 -
C++中的组合
所谓类的组合是指:类中的成员数据是另一个类的对象或者是另一个类的指针或引用。通过类的组合可以在已有的抽象的基础上实现更复杂的抽象。 例如:1、按值组合#include#includeclass Point{public: Point(int xx,int yy)//构造函数 { x=xx; y=yy; cout<<"Point's constructor was c原创 2013-06-21 21:22:12 · 527 阅读 · 0 评论 -
虚拟继承
虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如下图所示。 类D继承自类B1、B2,而类B1、B2都继承自类A,因此出现如上图(b)所示的局面(非虚基类)。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。最后原创 2013-06-21 21:51:30 · 645 阅读 · 0 评论 -
public、private和protected继承
1、public继承 public派生被称为类型继承。派生类型是基类的子类型,它改写了基类中所有与类型相关的成员函数,而继承了共享的成员函数。2、private继承 private派生被称为实现继承。派生类不直接支持基类的公有接口。3、protected继承 在protected继承下,基类的所有公有成员都成为派生类的protected成员。个人原创 2013-06-21 21:08:08 · 391 阅读 · 0 评论 -
C++中的RTTI
C++中的RTTI是指“运行时刻类型识别”。RTTI:Run-Time Type Identification。那么C++中的RTTI有什么作用呢?RTTI允许“用指向基类的指针或引用来操纵对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类类型。在C++中,为了支持RTTI提供了两个操作符:1、dynamic_cast操作符,它允许在运行时刻进行类型转换。把基类指针转换成派生类指针,原创 2013-06-22 20:25:22 · 562 阅读 · 0 评论 -
C++异常处理的知识点
1、在C++中,异常往往用类(class)来实现2、抛出异常可通过throw表达式来实现,throw表达式看起来非常像return语句,throw表达式由关键字throw后面跟一个表达式构成,该表达式的类型是被抛出异常的类型。例如://异常类class popOnEmpty{/* ... */};class pushOnFull{/* ... */};throw popOnEmpt原创 2013-06-05 16:37:30 · 387 阅读 · 0 评论 -
基类虚拟函数的异常规范
基类中虚拟函数的异常规范,可以与派生类改写的成员函数的异常规范不同。但是,派生类虚拟函数的异常规范必须与基类虚拟函数的异常规范一样或者更严格。例如:class Derived : public Base{public: //错误:异常规范没有Base::f1的严格 double f1(double) throw(string) ; //正确:与Base::f2()相同的异常规范 i原创 2013-06-22 21:00:36 · 936 阅读 · 0 评论 -
构造函数与函数try块
我们可以把整个函数包含在一个try块中,这种try块被称为函数try块。例如:int main()try{ //main()的函数体}catch(pushOnFull){ // ...}catch(popOnEmpty){ // ... } 函数try块对于类的构造函数来说是必须的。当一个类的构造函数在初始化时出现抛出异常,我们该如何处理呢?这时我们可以使用tr原创 2013-06-22 21:16:22 · 917 阅读 · 0 评论 -
继承和函数重载的问题
我们先看一个例子:class Base{public: void print(string) const ; // ...};class Derived1 : public Base{public: void print(int) const ; // ...};class Derived2 : public Base{public: void print(d原创 2013-06-23 17:09:11 · 406 阅读 · 0 评论 -
多继承
为支持多继承,一个类的派生表被扩展成支持逗号分割的基类表。例如:class Panda : public Bear,public Endangered { ... }; 每个被列出的基类还必须指定访问级别:public、protected或private之一。如果缺省没有列出,则其缺省值为private。例如:class Panda : public Bear,Endang原创 2013-06-21 20:38:12 · 368 阅读 · 0 评论 -
如何将一个函数声明为两个类的友元或将该函数作为一个类的成员,另一个类的友元
1、如果决定一个函数必须被声明为两个类的友元,则友元声明如下:class Window ; //只声明class Screen{ friend bool is_equal(Screen& scr,Window& win) ; //将is_equal函数声明为类Screen的友元};class Window{ friend bool is_equal(Screen& scr,W原创 2013-06-17 11:19:02 · 809 阅读 · 0 评论 -
类模板实例化
只有当代码中使用了类模板的一个实例名字,并且上下文环境要求必须存在类定义时,这个类模板才被实例化。并不是每次使用一个类都要求知道该类的定义。例如,如果我们只是声明一个类的指针和引用,就没有必要知道类的定义。例如:class Matrix ;Matrix *pm ; //声明一个类的指针,不需要Matrix的定义void inverse(Matrix&) ; //声明一个类的引用,不需要M原创 2013-06-20 16:01:10 · 625 阅读 · 0 评论 -
类模板的静态数据成员
在类模板中,也可以定义静态数据成员。例如:templateclass QueueItem{public: // .... private: // ... static QueueItem *free_list ; //静态数据成员 static const unsigned QueueItem_chunk ; //静态数据成员 // ... }原创 2013-06-20 19:29:33 · 941 阅读 · 0 评论 -
缺省构造函数
缺省构造函数是指不需要用户指定实参就可以被调用的构造函数,这并不意味着它不能接受实参。只是意味着构造函数的每个参数都有一个缺省值与之关联。例如,下面的每个函数都表示一个缺省构造函数://每个都是缺省构造函数Account::Account() { ... } iStack::iStack(int size=0){ ... } //存在一个参数,该参数有缺省值Complex::comple原创 2013-06-16 18:17:16 · 1220 阅读 · 0 评论 -
类的析构函数
析构函数是一个特殊的由用户定义的成员函数,如果我们没有创建它,系统会自动帮我们创建一个析构函数。这个是默认析构函数。当该类的对象离开了它的域,或者delete表达式(且其表达式值中的指针必须指向一个带有析构函数的类类型)应用到一个该类的对象的指针上时,析构函数会自动被调用。 注意,析构函数不能被重载。 并不是所有的类都需要析构函数。例如:class Point3原创 2013-06-13 20:45:49 · 469 阅读 · 0 评论 -
关键字explicit的作用
C++中explicit有什么作用? 关键字explicit可以禁止“单参数构造函数”被用于自动类型转换 class Stack { explicit Stack(int size); }; 没有explicit的话Stack s = 40;能编译通过。因为它会把40隐式转换成Stack对象。而有exp原创 2013-06-13 21:01:33 · 364 阅读 · 0 评论 -
浅复制构造函数和深复制构造函数
1、浅复制构造函数 编译器提供了默认构造函数、析构函数,同时也提供了赋值构造函数。编译器默认提供的复制构造函数只是把传递进来的对象的每个成员变量复制到新的成员变量中去。然后两个对象中的变量均指向存放类成员变量的那块内存区域。假设该变量不是指针变量一般不会立即出错。假设该变量是指针变量,如图: 现在对象a有一指针变量x,它指向堆中存放6的那块内存区域。我们将对原创 2013-06-16 21:38:26 · 411 阅读 · 0 评论 -
C++标准库的string类型与C 风格的字符串的相互转换
1、string类型能够自动将 C 风格的字符串转换成 string对象 string s1; const char *pc = "a character array"; //注意这里,因为C风格的字符串类型是const char*,所以=左边指针的类型必须是const char* s1 = *pc; //string转载 2013-05-04 15:17:01 · 1388 阅读 · 0 评论 -
重载操作符时将其声明为类成员还是非类成员的一个标准
一般我们应该怎样决定把一个操作符声明为了类成员还是名字空间成员呢?在某些情况下,程序员是没有选择的余地。1、如果一个重载操作符是类成员,那么只有当跟它一起被使用的左操作数是该类的对象时,它才被调用。如果该操作符的左操作数必须是其他的类型,那么重载操作符必须是名字空间成员。2、C++要求,赋值(=)、下标([ ])、调用(())和成员访问箭头(->)操作符必须被定义为类成员操作。任何把这些操原创 2013-06-17 11:41:44 · 719 阅读 · 0 评论 -
函数对象的理解
一、函数对象的定义首先有这么一个类,它重载了函数调用操作符[operator()],那么这个类定义的对象就叫做函数对象。关键的一点是:这个类重载了函数调用操作符“()”。那么为什么称为函数对象呢?针对与这一点的理解,下面会讲到。二、先看一个函数对象的实例//定义一个类LessThan,重载了函数调用操作符"()"class LessThan{public: bool opera原创 2013-06-05 05:11:34 · 371 阅读 · 0 评论 -
非类型参数的模板实参
类模板参数也可以是一个非类型模板参数。例如:templateclass Screen{ Screen() : _height(hi),_width(wid),_cursor(0),_Screen(hi*wid,'#') { } // ...private: string _Screen ; string::size_type _cursor ; short _height ;原创 2013-06-20 16:38:14 · 493 阅读 · 0 评论 -
类模板中的友元声明
有三种友元声明可以出现在类模板中:1、非模板友元类或友元函数。在下面的例子中,函数foo()、成员函数bar()以及foobar类都是类模板QueueItem的所有实例的友元。class Foo{ void bar() ;};templateclass QueueItem{ friend class foobar ; friend void foo() ; friend原创 2013-06-20 17:31:36 · 407 阅读 · 0 评论 -
指向基类的指针和指向派生类的指针之间的关系
指向基类的指针和指向派生类的指针之间有什么关系呢??先看下面的一个例子:class Base{ ... };class Derived1 : public Base{ ... };下面我们分别定义指向基类Base的指针和指向派生类Derived1的指针:Base *pb ;Derived1 *pd ;pb = new Derived1 ; //正确:因为pb指向一个在层次原创 2013-06-23 17:35:59 · 542 阅读 · 0 评论 -
类继承
1、继承机制的两种特性:多态和动态绑定2、当我们在C++说到多态性时,我们主要指基类的指针或引用可以指向其任意派生类的能力。也就是说,只有在通过基类指针或引用间接指向派生类子类型时,多态性才会起作用。一个对象的多态性操纵行为要求“通过指针或引用来访问该对象”,但是,在C++中,指针或引用的操作本身不一定导致多态性。例如://没有多态性int *pi ;//没有语言支持的多态性voi原创 2013-06-20 21:28:38 · 411 阅读 · 0 评论 -
私有派生
基类的私有派生指使用关键字private。例如:#include using namespace std ;class Father{public: void room() { cout << "父亲的大房子我可以享受!\n" ;}}; class Son : private Father // 从Father中私有派生的{};int main(){ Son原创 2013-07-09 21:13:40 · 485 阅读 · 0 评论 -
显示实例化声明
显示实例声明的格式:关键字template后面是函数模板实例的声明,其中显示地指定了模板实参。例如:template T sum(T t1,int t2) ;//显示实例化声明template int* sum(int*,int) ; 该显示实例化声明要求模板实参int*实例化模板sum()。对于给定的函数模板实例,显示实例化声明在一个程序中只能出现一次。注意temp原创 2013-05-30 10:56:55 · 785 阅读 · 0 评论 -
虚拟基类成员的可视性
我们首先看一个虚拟继承的例子:class Base{public: bar(int) ; // ...};class Derived1 : virtual public Base{ public: bar(char) ; // ...};class Derived2 : virtual public Base{public: foo(int) ; // ...原创 2013-06-23 18:09:57 · 430 阅读 · 0 评论 -
C++中的左值和右值
C++里左值和右值的区别是什么呢? 一般来说,左值,右值的概念用于赋值表达式。从字面上理解,左值在等号左边,右值在等号右边。左值我们用的是它的地址,有地址且可地址可用的实体都可以用作左值,右值我们用的是它的值,只要有一个值,就可以作为右值,比如:文字常量,变量。特别的,符号常量(const)对象中的值不能修改,所以只能用作右值。举例来说:int a; char b; a,b都原创 2013-06-22 11:16:35 · 471 阅读 · 0 评论 -
转换函数
转换函数是一种特殊类型的类成员函数。它定义了一个由用户定义的转换,以便把一个类对象转换成某种其他的类型。在类体中通过指定关键字operator,并在其后加上转换的目标类型后,我们就可以声明转换函数。转换函数采用如下的一般形式:operator type() ; 这里的type可用内置类型,类类型或typedef名取代。但是不允许表示数组或函数类型。转换函数必须是成员函数,它的声明原创 2013-06-17 21:41:13 · 717 阅读 · 0 评论 -
typedef与宏定义区别
typedef与宏定义区别 个人觉得这篇文章写得非常好,就转了。我转载的这篇文章的地址为http://i.mtime.com/ocgcyj/blog/5693781/。 陷阱一: 记住,typedef是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。比如: 先定义: typedef char* PSTR; 然后: in转载 2013-04-30 15:59:30 · 40230 阅读 · 0 评论 -
指向函数的指针
1、什么叫指向函数的指针呢? 简单来说,就是该指针的指向是一个函数,普通的指针是指向一个变量等,而指向函数的指针就是该指针指向的是函数。它的定义形式可以用下的例子说明: int (*pf) ( const string&, const string& ) ; 这个语句说明了pf是一个指向函数的指针,该函数有两个参数和int类型的返回值。上面的语句该原创 2013-05-17 11:00:40 · 361 阅读 · 0 评论 -
为什么const对象只能访问const成员函数
为什么const对象只能访问const成员函数??但是,非const对象可以调用const函数!!!! C++ Primer中说了,在一个对象调用其成员函数时,它隐含的一个形参this指针。这是有编译器完成的。那么我们下面看下编译器是如何完成的,分成两步:1、改变类的成员函数的定义。用额外的参数:this指针,来定义每个成员函数。例如://伪代码,说明编译器对一个成员函数定转载 2013-06-10 14:52:09 · 65350 阅读 · 0 评论 -
操作符new和delete(作为类的成员操作符)
1、操作符new() 我们可以把操作符new()声明为类的成员函数。不过要注意的是,类成员操作符new()的返回类型必须是void*,并且有一个size_t类型的参数,这里的size_t是一个在系统头文件中被定义的typedef。下面举一个例子://在Screen类中声明操作符newclass Screen{public: void* operator new(size_t原创 2013-06-17 21:00:40 · 642 阅读 · 0 评论 -
联合体的内存大小
解惑:sizeof(联合)这个值是怎么计算的[不要只做技术]在论坛上问如下代码结果为什么是24? union DATE { char a; int i[5]; double b; }; DATE max; cout 这个问题很好回答,并且我把这个问题归结于基本概念题(就是入门书必须介绍的)。我想一般来说,做过内存管转载 2013-09-05 00:19:50 · 750 阅读 · 0 评论 -
c++空类实例大小不是0原因
《深度探索c++对象模型》中是这样说的:那是被编译器插进去的一个char ,使得这个class的不同实体(object)在内存中配置独一无二的地址。也就是说这个char是用来标识类的不同对象的 初学者在学习面向对象的程序设计语言时,或多或少的都些疑问,我们写的代码与最终生编译成的代码却 大相径庭,我们并不知道编译器在后台做了什么工作.这些都是由于我们仅停留在语言层的原因,所谓语言层转载 2013-08-05 23:11:49 · 351 阅读 · 0 评论 -
C/C++中的联合 union
联合(union)在C/C++里面见得并不多,但是在一些对内存要求特别严格的地方,联合又是频繁出现,那么究竟什么是联合、怎么去用、有什么需要注意的地方呢?就这些问题,我试着做一些简单的回答,里面肯定还有不当的地方,欢迎指出!1、什么是联合? “联合”是一种特殊的类,也是一种构造类型的数据结构。 在一个“联合”内可以定义多种不同的数据类型, 一个被说明为该“联合”类型的转载 2013-07-27 22:07:09 · 669 阅读 · 0 评论 -
基类对象和派生类对象之间的赋值关系
基类对象和派生类对象之间的赋值关系具体是指:基类的对象可不可以赋值给子类对象或者子类对象可不可以赋值给基类对象。 一般来说,只有派生类的对象可以赋值给基类的对象,反之,则不可以。例如:Father a ; // 基类对象Son b ; // 派生类对象a = b ; // 可以b = a ; // 不可以 为什么原创 2013-07-09 20:38:17 · 2396 阅读 · 0 评论 -
友元函数和友元类
采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和原创 2013-06-23 11:24:25 · 375 阅读 · 0 评论 -
系统是如何调用虚函数
系统是如何调用虚函数的? 每个对象创建虚函数时,对象都记得记录这个虚函数,因此编译器建立一个叫做T表的虚函数表。每个对象都有一个指向该表的指针,叫做虚表指针。该指针用来指向虚函数表。相反虚函数表也有一个指针指向该对象,当创建派生类对象的基类部分时,该对象的指针就自定初始化为指向虚函数表的正确部分。当调用派生类对象的构造函数时,这个对象就会添加到虚函数表中去,并且将指针指向该对象的重原创 2013-07-13 11:19:19 · 353 阅读 · 0 评论 -
返回值优化
通过传值方式返回要创建新对象时,应注意使用的形式,例如在operator+:return Integer(left.l / right.l) ; 咋看起来这像是一个“对一个构造函数的调用”,其实并非如此。这是临时对象语法,它是在说:“创建一个临时Integer对象并返回它”。据此我们可能认为如果创建一个有名字的局部对象并返回它结果是一样的。其实不然。如果如许编写:Integer原创 2013-07-31 10:26:58 · 383 阅读 · 0 评论