3.静态局部变量直到程序终止时才退出,C++支持多

作者: 编程  发布:2019-09-25

1.什么是面向对象?

概念:(Object Oriented Programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法。
对象指的是类的实例,将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。

9159.com 1

C++不是纯面向对象语言,而是基于面向对象的语言
(ps:因为它包含C的部分,C是面向过程)

面向对象三大特性:封装、继承、多态

C++简介:

            C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛;C++支持多种编程范式 --面向对象编程、泛型编程和过程化编程。最新正式标准C++于2014年8月18日公布。[1]其编程领域众广,常用于系统开发,引擎开发等应用领域,是至今为止最受广大程序员受用的最强大编程语言之一,支持类:类、封装、重载等特性。

1.struct成员默认访问方式是public,而 class默认访问方式是private!

C++学习笔记

1.struct成员默认访问方式是public,而 class默认访问方式是private

2.exit函数终止程序执行会调用析构函数 ,abort函数终止程序不会调用析构函数

3.静态局部变量直到程序终止时才退出

4.通过public 函数返回 private成员的引用有可能会破坏类的封装 ,造成外部变量可以改变类私有成员值

5.常量对象只能调用常量成员函数,常量成员函数可以有非常量版本重载

6.常量数据成员只能在定义时初始化或者在构造函数里用成员初始化值来初始化 ,不能用赋值语句来初始化

7.要在析构函数里面使用delete来释放使用 new申请的内存空间

8.编写析构函数来释放类中成员所申请的内存空间和使用深拷贝函数是好的编程习惯

9.operator++()是相当与++d,operator++(int) 是相当于 d++

10.如果父类中函数是虚拟函数 ,那么在每个子类中显式声明虚拟函数是好的编程习惯

11.如果类作为基类,其析构函数要声明为虚析构函数 ,这样派生类才可以调用自己的析构函数

12.一个new 就对应一个 delete是好的编程习惯

13.istream输入read 是从文件中读取 ,ostream输出write 是写到文件中去

14.istream是seekg 重置文件指针位置 ,ostream是seekp, 文件用file.eof()来判断是否读取到文件尾部

15.assert(条件), 当满足条件时就不 assert,不满足条件才会assert

16.对于不需要修改的变量,使用常量引用来传递参数可以既保证安全性又保证效率

17.在循环之前调用srand(time(0)),然后在循环中调用 rand()函数可以使得每次随机的结果都不相同

18.一维数组形参如下:int a[],二维数组形参如下 :int a[][SIZE],第一个[] 是空的,后面必须非空

19.#define A 10 后面没有分号

20.在局部函数中用new创建的变量是存在内存中的,即便局部函数执行完毕内存变量仍然存在,但是指向它的指针有可能是局部变量,则需要在局部函数结束前调用 delete释放内存空间,以免内存泄漏

21.数组声明最好用 T *a 来声明 ,这样不容易出错,创建对象最好用 new 而不是直接创建

22.定义一个类时,析构函数(释放资源)和拷贝构造函数(深拷贝)最好显示定义

23.C/C++语言输入结束符是ctrl+z(windows下 )

24.C语言的printf(“%.9lf”,a); 比c++的 setprecision(10)来的更加精确,C++有时自动舍入精度

25.理清状况,逻辑严谨,变量初始化、是还是否、边界判断判断正确

26.要使得栈中的基本元素是模板类类型,必须要定义模板类的一些函数:默认构造函数,友员输出函数等

27.用单件模式和全局函数替代全局变量,以便于拓展和维护

28.用const char ptr 表示ptr指向的变量为常量。 char const ptr表明ptr 本身为常量是好的编程习惯

29.const int *i = &a, 只是代表不能通过 i指针来修改,但是可以通过其它途径来修改 a,例如a=3

30.灵活熟练运用语言,如 (a<b?a:b<c?b:c) = val();这句话就将3 个if语句合并成一句话

31.桥接模式bridge 可以实现接口与实现分离 ,这样可以减少修改类时需要修改的类的范围

32.优先级:i++ 高于 ++i ,注意,具体运算符优先级看下面的运算符优先级表

33.递归算法符合大致算法思想就行了 ,不必深究思考,合理就可以了

34.在C++ 中使用0来对指针初始化可以保证数字字面常量 0可以转换成任何一种指针类型对应的空指针

35.非const 对象可以调用 const和非const 函数,但是 const对象只能调用const函数

36.可以使用非const 类型变量赋给 const类型参数,不能用const类型变量赋值给非 const类型参数

37.类重载二元运算符时,要么作为类的只带一个参数的内部函数 ,要么作为类中带两个参数的友元函数

38.内建的operator-> 是二元的 ,而重载的operator-> 是一元的 ,如果重载了operator-> 则先调用重载的 ,直到重复调用到内建的operator->才终止

39.尽量使用STL 是好的编程习惯

40.++i返回的是内存变量,可以作为左值也可以作为右值 ,而i++ 返回的是字面量 ,不占内存, 不能作为左值右值

41.for循环中使用continue 不会出现死循环 ,但是while 中使用continue容易出现死循环 ,因为可能i 没有自加

42.取最大优先分析原则会取最长的类型 ,所以要这么义:list

43.对于平凡整型常量,可以用枚举量来表示

44.派生类赋值给基类是不要使用对象继续赋值 ,而是使用指针或引用以避免发生截切

45.不使用 void * 为类型转换的中介类型是良好的编程习惯 ,因为void * 会抹除指针的类型信息

46.使用引用类型或标准库组件以避免引入多级指针的复杂性是较佳的设计

47.在类对象中尽量避免使用二级指针 ,尤其是在基类指向派生类对象的指针时尤其要注意

48.在C++ 类中尽量不要重载类型转换 operator函数, 而是使用有明确含义的如 toInt(),toChar()等函数替代

49.C++中有时在类构造函数前加上 explicit关键字来禁止隐式类型转换可以减少很多错误

50.多用引用传递参数,用值传递时会有大量的复制操作 ,效率很低, 多用引用是好的编程习惯

51.函数对象就是重载了operator()的 class对象, 使用函数对象生成匿名临时对象是好的编程习惯

52.使用dynamic_cast<>,static_cast<>,const_cast<>,reinterpret_cast<>

53.在派生类构造函数中尽量多使用成员初始化列表 ,静态数据成员和数组不允许在成员初始化表中进行初始化 ,可以在函数体中进行初始化

54.在类中涉及到指针和引用等 ,最好显示撰写深拷贝构造函数和赋值运算符重载 operator=(),以免出现错误

55.子类在继承父类时如果重写父类的虚函数或者非虚函数 ,要保证在子类中重写的函数访问修饰符和父类结合继承访问后得到的访问修饰符结果一致

56.在写拷贝构造函数和重写赋值运算符函数时必须把类中所有变量都用 '='号显示写全了,不要写一部分 ,如果你没写, 则编译器只会调用默认构造函数进行变量初始化 ,而不会默认用'='号

57.尽量不要在类中使用静态变量 ,永远不要做运行期静态初始化

58.对class 对象或者有可能是 class对象的实体进行直接初始化而不是用赋值语句初始化 ,如:N n(0)

59.搞清楚复制初始化和赋值初始化的不同 ,复制初始化是调用拷贝构造函数实现 ,而赋值是重载'='实现

60.可以通过在private 区域声明拷贝构造函数来禁止类的复制初始化

61.对象作为参数尽量使用引用传递 ,其次考虑指针,尽量不要用值传递 ,如果不想修改对象可以加 const

62.抛出匿名临时异常对象,并以引用的方式捕获它们 ,如需重新抛出,则抛出既有的异常对象 ,而非处理原始的异常之后 ,抛出一个新的异常对象

63.不要返回函数作用域内所分配的存储的引用(返回指针或直接传值可以) ,会造成内存泄漏

64.使用类的构造函数和析构函数来封装一些成对的操作如加锁和解锁等 ,这样在函数执行开始时创建类对象 ,使用A a; 而不适A a();或 A()来创建, 在函数结束前会自动删除改对象 ,也就实现了开始时调用加锁操作 ,结束时调用解锁操作,俗称 RAII(资源获取即初始化)

65.复制auto_ptr 模板实例化对象将指向的对象的控制权转移 ,然后把复制源设为空

66.永远不要把auto_ptr 实例化的类型作为 STL容器的基本类型

67.不要将auto_ptr 对象作为函数参数按值传递 ,会清空原有对象,造成不可预知的错误

68.不要在虚函数中提供参数的默认初始化物

69.访问层级(public protected private) 对重写虚函数没有任何影响 ,即使public 继承,你也可以将继承过来的本来应该是 public的函数写到private 作用域中 ,完全可以

70.派生类中对基类中的非虚函数的重写或重载其实是遮掩 ,会将基类中同名的所有虚函数和非虚函数全部遮掩 ,使之无效, 这时想要构成重载 ,必须使用using A::fun() 函数来导入基类中 fun函数

71.重载必须在同一个类作用域下才构成重载 ,否则只是遮掩

72.重载虚函数要么对基类中的每一个都重写要么一个都不要重写 ,或者使用using A::fun()

73.C++中尽量避免使用指针,而是使用引用

74.复制操作不经由模板成员函数来实现 ,必须显示给出复制操作的实现

75.用户自定义版本的后置式形式自增自减运算符应该返回常量 ,因为后置后置不能作为左值

76.前置式总是优于后置式,即 ++i总是优于i++

77.非成员友员允许在第一个参数上施行类型转换 ,而成员函数不能在第一个参数上施行类型转换

78.在进行指针重新复制时一定要注意是否可能造成内存泄漏 ,是否要先释放当前指针所指内存空间

79.mutable变量可以在const 函数中被修改 ,其效果好于const_cast<>, 所以尽量使用 mutable

80.类重载运算符时有时必须参数和函数都是 const,这样保证在其他函数调用时即使传递常量参数也没问题

81.变量传递给常量参数可以 ,但是常量传递给变量参数却不行

82.多使用虚函数实现不同的功能 ,把基类尽量细分成更小的基类

83.使用动态绑定而不是条件式的分派实现类型相关的需求

84.如果某个类型可能成为基类 ,则一开始就把它写成抽象基类

85.以public 方式继承的基类一般应该是抽象的 ,应该集中精力于接口继承而不是代码复用

86.接口类就是没有数据成员 ,析构函数声明为虚函数,普通成员函数皆为纯虚函数 ,不声明构造函数的类型

87.要么public, 要么友元函数 ,其它如protected 继承后的函数交叉调用可能会出现问题

88.尽量不使用class 数组,多用 STL容器, 如vector,而且容器类型是指针而不是对象 ,如vector

89.wget w1 = w2;调用拷贝构造函数,而 wget w1;w1 = w2;调用的是类赋值运算符

90.类参数传值传递是调用拷贝构造函数 ,多用const 引用

91.enum{star=5};这里定义的star 可以当作常量字面量来用 ,和#define star 5 效果是一样的

92.尽量使用const,enum,inline 来代替#define,使用模板 inline函数代替宏

93.对于单纯常量,最好用 const和enum 代替#define,对于形似函数的宏 ,最好使用inline 函数来替代

94.如果const 出现在左边则所指的是常量 ,如果const 出现在右边 ,则指针是常量

95.STL中const vector

96.函数的const 版本可以和原版本重载 ,用非const 函数调用 const函数可以减少代码重复

97.使用函数返回静态对象将 non-local static对象转化为locat static 对象

98.引用的赋值相当于把等号右边别名所指的对象值替换了等号左边别名所指对象的值,还是 2个对象

99.可以通过声明纯虚析构函数来定义一个抽象类 ,这时纯虚析构函数必须给出定义才行

100.析构函数绝对不要吐出异常 ,即使出现异常也要在析构函数内部处理 ,要么结束要么吞下

101.不要在构造函数和析构函数中调用 virtual函数, 不会下降到 derived class类别, 用向上传递参数替换

102.令赋值操作符返回一个reference to *this

103.派生类中的拷贝构造函数和赋值符号不会自动拷贝或赋值基类部分 ,所以要显示调用基类拷贝或赋值函数

104.在释放内存空间时先把原指针所指内存区域备份 ,再删除或指向新的内存空间 ,再delete 原来备份的区域

105.多使用tr1::shared_ptr 和auto_ptr智能指针来自动释放内存空间

106.类中尽量不要定义类型转换符号 ,即使定义也没有返回类型 ,因为类型转换符本身已经规定了返回类型

107.shared_ptr对象如果有多个指向一个指针 ,则只有第一个需要使用指针初始化 ,其他的要么用拷贝构造函数 ,要么用赋值运算符初始化 ,指针初始化只能用一次

108.对于内置类型、STL和函数对象 ,传值比较高效,但是对于其它类型 ,传递常量引用比较高效

109.引用和指针一样支持多态性 ,因为引用的内部就是通过指针实现的

110.尽量用non-member 和non-friend函数替换 member函数

111.如果一个函数和类相关,但不是成员函数 ,那么该函数也不一定非得是友元函数 ,如果函数能通过类的公共接口完成功能 ,则完全不必声明为友元函数 ,但该函数返回值一般是const

112.构造函数如果不是explicit则可以进行隐式类型转换 ,不管构造函数有几个参数 ,但前提是如果你给的实际参数个数小于构造函数需求参数个数 ,你得保证构造函数有默认构造参数

113.一个类内对象内部函数可以访问对象自己的私有成员变量 ,但是如果有一个同类的另一个对象作为函数的参数 ,则该内部函数也可以访问另一个对象的私有成员变量

114.尽量往后定义变量的出现 ,最好能等到变量不仅需要被使用而且初值也确定时再定义

115.尽量避免使用转型,即使必须使用也得使用 C++特定的如static_cast 等!

116.虚析构函数都是public,没有其它的像 private和protected 类型的

117.根据实际需要选准模式,是 is-a 还是has-a,private 继承和has-a类似 ,但是一般都是会选择has-a

118.因为private 继承不是 is-a关系, 所以不能满足基类指针指向派生类的情况 ,当然不能使用多态性,只能看作是和 has-a一样的情况了

119.virtual函数即使是private 函数且被 private继承, 虽然对于派生类不可访问 ,但派生类还是可以继承基类 virtual函数并重写的,并无影响

120.指针可以改变其指向的对象 ,但是引用不行,引用一旦赋值后不能改变

121.重载某个操作符时应该返回引用而不是指针

122.隐式转换最多只能转换一次 ,超过一次就被禁止

123.前缀返回引用,后缀返回 const value,后缀通过前缀实现,前缀效率比后缀高

124.在析构函数中释放资源,尽量使用引用来捕捉异常 ,而不用传值或指针

125.模板和异常规格不要混合使用 ,异常规格是一个应该被审慎使用的特性

126.STL中对于iterator 尽量运用 (*iterator).first来取值, 而不是用 ->来取值

127.C++禁止为非常量引用创建临时变量 ,所以非常量引用传递参数时不会发生隐式类型转换

128.常量引用是会创建临时变量的 ,这时会发生隐式类型转换

129.每一个重载运算符必须自带至少一个用户自定义类型的参数

130.操作符 -> 优先级高于 * !

131.每种类有一个vtbl,每个对象有一个 vptr,RTTI是在vtbl 中增加一项 ,所以只会增加类大小,而不会增加对象大小

132.析构函数必须被定义

133.auto_ptr对象最好使用const引用传递 ,而不要用值传递

134.编译器只能默认帮你进行一次类型转换 ,超过一次就不行

135.对灵巧指针绝对不要提供一个转换到原始指针类型的转换操作符

136.当使用类型转换太麻烦时 ,不妨就使用模板吧

137.一定要为含有指针的类提供深拷贝构造函数 ,以免在以后的运用中出现错误

138.构造函数和析构函数可以被子类继承 ,但如果析构函数是虚函数 ,继承的子类的析构函数也默认是虚函数 ,但你最好加上virtual增加可读性

139.cout<<setiosflags(ios::fixed)<<setprecision(n)<<s1<<endl; 用来设置 C++中输出小数点后位数

140.使用extern “C” 可以将函数变成 c函数风格, 即obj文件中不能进行名变换

141.将十进制化为二进制或判断能否被 2整除或者除以2可以使用右移操作和 &1操作

142.C++和C语言中,把整数赋值给字符变量,是将整数当作ASCII码赋给字符变量,将字符变量赋值给整数也是将字符变量对应的ASCII码赋给整数

143.C++中STL容器的工作方式是对内建类型是位拷贝,自定义对象是存入对象的拷贝,使用insert或是push_back时都是使用拷贝,如果创建对象时是在堆中,则传指针给STL,如果在栈中,则传递对象本身

144.C++中使用STL容器时,若对象拷贝动作较多,基类又要记录派生类,则存放指针,若是基本类型或者很少拷贝,则存放对象

2.类的大小?为什么要内存对齐?内存对齐的计算?空类的计算

①类的大小(是不是很疑惑,类肿么还有大小,不就是个类型嘛,纳尼)
是的类有大小,看个栗子:

class Book{public:    Book();    void Show;private:    char name[10];    int isbn;};

![这里写图片描述](https://img-blog.csdn.net/20180328233423113?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;有没有算出来。其实类和我们结构体一样是有大小的,而且类的内存对齐方式和结构体一样。**②为什么要内存对齐?**这个要说到操作系统上了,我们的cpu把内存当成是一块一块的,块的大小可以是2,4,8,16 个字节,因此CPU在读取内存的时候是一块一块进行读取的,块的大小称为(memory granularity)内存读取粒度。**为什么要分块呢?**(分块读取有利于提高内存访问效率)**和内存对齐有什么关系?**  假设CPU要读取一个4字节大小的数据到寄存器中(假设内存读取粒度是4),分两种情况讨论:   1.数据从0字节开始  2.数据从1字节开始解析:当数据从0字节开始的时候,直接将0-3四个字节完全读取到寄存器,结算完成了。当数据从1字节开始的时候,问题很复杂,首先先将前4个字节读到寄存器,并再次读取4-7字节的数据进寄存器,接着把0字节,4,6,7字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器,对一个内存未对齐的寄存器进行了这么多额外操作,大大降低了CPU的性能。所以内存对齐就很好的提高了cpu的读取效率。**内存对齐的计算?**1.第一个成员在与结构体变量偏移量为0的地址处。2.其他成员变量要对齐到某个数字的整数倍的地址处。**对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。**VS中默认的值为8gcc中的默认值为43.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。**空类的计算**先说答案:空类的大小是1![这里写图片描述](https://img-blog.csdn.net/20180328234728908?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)#3.类的6个默认成员函数的详细使用及细节 c++的类有六个默认成员函数:![默认成员函数](https://img-blog.csdn.net/20180328235158617?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)我们常用的是前四个。**1)构造函数:**成员变量为私有的,要对它们进行初始化,必须用一个公有成员函数来进行。同时这个函数应该有且仅在定义对象时自动执行一次,这时调用的函数称为构造函数(constructor) 。构造函数是特殊的成员函数,其特征如图:![这里写图片描述](https://img-blog.csdn.net/20180329170158905?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)构造函数基本我们都使用全缺省的重载函数。**2)拷贝构造函数:**创建对象时使用同类对象来进行初始化,这时所用的构造函数称为拷贝构造函数(Copy Constructor),拷贝构造函数是特殊的构造函数。来个例子:

class Book
{
public:
Book;
Book(int isbn = 0x00, char name = "图书");
private:
int isbn;
char
name;
};

int main
{
Book b;
Book b1; //这里使用了拷贝构造
system;
return 0;
}

特征:**☛** 拷贝构造函数其实是一个构造函数的重载。**☛** 拷贝构造函数的参数必须使用引用传参,使用传值方式会引发无穷递归调用。**☛** 若未显示定义,系统会默认缺省的拷贝构造函数。缺省的拷贝构造函数会,依次拷贝类成员进行初始化。一般情况下我们会使用系统默认的拷贝构造函数,但是在特殊情况下需要显示定义(比如链表的拷贝构造)**3)析构函数**当一个对象的生命周期结束时,C++编译系统会自动调用一个成员函数,这个特殊的成员函数即析构函数(destructor)构造函数是特殊的成员函数,其特征如下:**☛**析构函数在类名加上字符~。**☛**析构函数无参数无返回值。**☛** 一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数。**☛**对象生命周期结束时,C++编译系统系统自动调用析构函数。**☛** 注意析构函数体内并不是删除对象,而是做一些清理工作。(怎么理解这里的清理工作?参看下面的代码)

class Date
{
public :
// 析构函数
~Date()
{}
private :
int _year ;
int _month ;
int _day ;
};

class Array
{
public :
Array
{
_ptr = malloc( sizesizeof ;
}
// 这里的析构函数需要完成清理工作。
~ Array ()
{
if
{
free;
_ptr = 0;
}
}
private :
int* _ptr ;
};
```

4)赋值操作符重载
为了增强程序的可读性,C++支持运算符重载。
运算符重载特征:
operator+ 合法的运算符 构成函数名(重载<运算符的函数名:operator< )。
重载运算符以后,不能改变运算符的优先级/结合性/操作数个数。
5个C++不能重载的运算符: .*/::/sizeof/?:/.

5)取地址操作符重载

class Date{public :Date* operator &(){return this ;}const Date * operator&() const{return this ;}private :int _year ; // 年int _month ; // 月int _day ; // 日};

6)const修饰的取地址操作符函数
在成员函数后面加const,const修饰this指针所指向的对象,也就是保证调用这个const成员函数的对象在函数内不会被改变。

class Date{public :void Display (){cout<<"Display ()" <<endl;cout<<"year:" <<_year<< endl;cout<<"month:" <<_month<< endl;cout<<"day:" <<_day<< endl<<endl ;}void Display () const   //const成员函数{cout<<"Display () const" <<endl;cout<<"year:" <<_year<< endl;cout<<"month:" <<_month<< endl;cout<<"day:" <<_day<< endl<<endl;}private :int _year ; // 年int _month ; // 月int _day ; // 日};void Test (){Date d1 ;d1.Display ();const Date d2;d2.Display ();}

后两个成员函数用的很少。

详细例题会在后面博文中专门解释。

原文链接:
专栏链接:

头文件与类的声明: 

---Header(头文件)的布局

(以课程为例)

#ifndef _COMPLEX_   //防卫式声明

#define _COMPLEX_

#include<iostream>//前置声明

class Complex{  //类声明

//class body

public://访问级别  包含public private  protect,             //这里未介绍第三个

      //成员函数

private:

//数据成员

};

#endif 

2.exit函数终止程序执行会调用析构函数 ,abort函数终止程序不会调用析构函数!

构造函数:

当一个类常见对象时自动调用的函数 ,当一个类的都早函数未定义是编译器会西东生成一个构造函数。构造函数没有返回值类型,可以有不同的参数列表(构造函数重载) 

class  Complex{

publlic:

Complex();

Complex(int a,int b);

~Complex();//当然存在析构函数用来释放对象所使                      //用的内存空间

private:

//....

}

3.静态局部变量直到程序终止时才退出!

参数传递与返回值:

参数:

参数的书写要完整,良好的书写风格赢不胜罗参数的名字

void setValue(int w,int h)//良好的风格

void setValue(int ,int )//不良的风格

参数命名要恰当,顺序合理;

如果输入参数是指针且仅作输入用,则应在参数类型前加const

void StringCopy(char* str,const char* strsorce)

如果输入参数咦值传递的方式传递对象,则应用“const&"方式来传递构造和析构过程,从而提高效率。

返回值:

如果返回的是哟个对象,有些场合用“引用传递”替换“值传递”可以提高效率。

class comples{

public:

complex(double r=0,double i=0){};

complex& operator += (const complex&);

double real() const{return re;}

4.通过public 函数返回 private成员的引用有可能会破坏类的封装 ,造成外部变量可以改变类私有成员值!

关于友元函数:

友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。

使用关键字:firend

相同的class的各个objects互为friends(友元)

class complex

{

public:

complex();

int func();

};

{complex c1;

complex c2;

c2.func(c1);

}

5.常量对象只能调用常量成员函数,常量成员函数可以有非常量版本重载!

操作符的重载与临时对象:

operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名。

运算符重载分为成员函数重载和友元函数重载两种。

成员函数重载:

inline complex& 

complex::operator+= (this,const complex& r){

return ...

}

友元函数重载:

friend operator +=( const complex& x,const complex& y){

...

}

临时对象(temp object):

1.用构造函数作为隐式类型转换函数是,会自动创建对象。

2.建立一个无名对象是会产生临时对象。

3.函数返回一个对象值时,会产生临时对象,函数中的返回值会以值拷贝的形式拷贝到被调函数栈中的一个临时对象。

同时

inline complex

operator+ (const complex& x, const complex& y){

return  ...}

inline complex operator +(const complex& x,double y){}

不可return by reference ,因为它们返回的必定是local boject.

整理自《C++面向对象程序设计》

6.常量数据成员只能在定义时初始化或者在构造函数里用成员初始化值来初始化 ,不能用赋值语句来初始化!

7.要在析构函数里面使用delete来释放使用 new申请的内存空间!

8.编写析构函数来释放类中成员所申请的内存空间和使用深拷贝函数是好的编程习惯!

9.operator++()是相当与++d,operator++(int) 是相当于 d++ !

10.如果父类中函数是虚拟函数 ,那么在每个子类中显式声明虚拟函数是好的编程习惯!

11.如果类作为基类,其析构函数要声明为虚析构函数 ,这样派生类才可以调用自己的析构函数!

12.一个new 就对应一个 delete是好的编程习惯!

13.istream输入read 是从文件中读取 ,ostream输出write 是写到文件中去!

14.istream是seekg 重置文件指针位置 ,ostream是seekp, 文件用file.eof()来判断是否读取到文件尾部!

15.assert(条件), 当满足条件时就不 assert,不满足条件才会assert!

16.对于不需要修改的变量,使用常量引用来传递参数可以既保证安全性又保证效率!

17.在循环之前调用srand(time(0)),然后在循环中调用 rand()函数可以使得每次随机的结果都不相同!

18.一维数组形参如下:int a[],二维数组形参如下 :int a[][SIZE],第一个[] 是空的,后面必须非空!

19.#define A 10 后面没有分号!

20.在局部函数中用new创建的变量是存在内存中的,即便局部函数执行完毕内存变量仍然存在,但是指向它的指针有可能是局部变量,则需要在局部函数结束前调用 delete释放内存空间,以免内存泄漏

21.数组声明最好用 T *a 来声明 ,这样不容易出错,创建对象最好用 new 而不是直接创建!

22.定义一个类时,析构函数(释放资源)和拷贝构造函数(深拷贝)最好显示定义!

23.C/C++语言输入结束符是ctrl+z(windows下 )!

24.C语言的printf(“%.9lf”,a); 比c++的 setprecision(10)来的更加精确,C++有时自动舍入精度!

25.理清状况,逻辑严谨,变量初始化、是还是否、边界判断判断正确!

26.要使得栈中的基本元素是模板类类型,必须要定义模板类的一些函数:默认构造函数,友员输出函数等!

27.用单件模式和全局函数替代全局变量,以便于拓展和维护!

28.用const char ptr 表示ptr指向的变量为常量。 char const ptr表明ptr 本身为常量是好的编程习惯!

29.const int *i = &a, 只是代表不能通过 i指针来修改,但是可以通过其它途径来修改 a,例如a=3 !

30.灵活熟练运用语言,如 (a<b?a:b<c?b:c) = val();这句话就将3 个if语句合并成一句话!

31.桥接模式bridge 可以实现接口与实现分离 ,这样可以减少修改类时需要修改的类的范围!

32.优先级:i++ 高于 ++i ,注意,具体运算符优先级看下面的运算符优先级表!

33.递归算法符合大致算法思想就行了 ,不必深究思考,合理就可以了!

34.在C++ 中使用0来对指针初始化可以保证数字字面常量 0可以转换成任何一种指针类型对应的空指针!

35.非const 对象可以调用 const和非const 函数,但是 const对象只能调用const函数!

36.可以使用非const 类型变量赋给 const类型参数,不能用const类型变量赋值给非 const类型参数!

37.类重载二元运算符时,要么作为类的只带一个参数的内部函数 ,要么作为类中带两个参数的友元函数!

38.内建的operator-> 是二元的 ,而重载的operator-> 是一元的 ,如果重载了operator-> 则先调用重载的 ,直到重复调用到内建的operator->才终止!

39.尽量使用STL 是好的编程习惯!

40.++i返回的是内存变量,可以作为左值也可以作为右值 ,而i++ 返回的是字面量 ,不占内存, 不能作为左值右值!

41.for循环中使用continue 不会出现死循环 ,但是while 中使用continue容易出现死循环 ,因为可能i 没有自加!

42.取最大优先分析原则会取最长的类型 ,所以要这么义:list<vector<string> > lovos;右边两个>> 之间必须有空格 ,如果没有则编译器可能解释成 >>右移操作符!

43.对于平凡整型常量,可以用枚举量来表示!

44.派生类赋值给基类是不要使用对象继续赋值 ,而是使用指针或引用以避免发生截切!

45.不使用 void * 为类型转换的中介类型是良好的编程习惯 ,因为void * 会抹除指针的类型信息!

46.使用引用类型或标准库组件以避免引入多级指针的复杂性是较佳的设计!

47.在类对象中尽量避免使用二级指针 ,尤其是在基类指向派生类对象的指针时尤其要注意!

48.在C++ 类中尽量不要重载类型转换 operator函数, 而是使用有明确含义的如 toInt(),toChar()等函数替代!

49.C++中有时在类构造函数前加上 explicit关键字来禁止隐式类型转换可以减少很多错误!

50.多用引用传递参数,用值传递时会有大量的复制操作 ,效率很低, 多用引用是好的编程习惯!

51.函数对象就是重载了operator()的 class对象, 使用函数对象生成匿名临时对象是好的编程习惯!

52.使用dynamic_cast<>,static_cast<>,const_cast<>,reinterpret_cast<> !

53.在派生类构造函数中尽量多使用成员初始化列表 ,静态数据成员和数组不允许在成员初始化表中进行初始化 ,可以在函数体中进行初始化!

54.在类中涉及到指针和引用等 ,最好显示撰写深拷贝构造函数和赋值运算符重载 operator=(),以免出现错误!

55.子类在继承父类时如果重写父类的虚函数或者非虚函数 ,要保证在子类中重写的函数访问修饰符和父类结合继承访问后得到的访问修饰符结果一致!

56.在写拷贝构造函数和重写赋值运算符函数时必须把类中所有变量都用 '='号显示写全了,不要写一部分 ,如果你没写, 则编译器只会调用默认构造函数进行变量初始化 ,而不会默认用'='号!

57.尽量不要在类中使用静态变量 ,永远不要做运行期静态初始化!

58.对class 对象或者有可能是 class对象的实体进行直接初始化而不是用赋值语句初始化 ,如:N n(0)!

59.搞清楚复制初始化和赋值初始化的不同 ,复制初始化是调用拷贝构造函数实现 ,而赋值是重载'='实现!

60.可以通过在private 区域声明拷贝构造函数来禁止类的复制初始化!

61.对象作为参数尽量使用引用传递 ,其次考虑指针,尽量不要用值传递 ,如果不想修改对象可以加 const!

62.抛出匿名临时异常对象,并以引用的方式捕获它们 ,如需重新抛出,则抛出既有的异常对象 ,而非处理原始的异常之后 ,抛出一个新的异常对象!

63.不要返回函数作用域内所分配的存储的引用(返回指针或直接传值可以) ,会造成内存泄漏!

64.使用类的构造函数和析构函数来封装一些成对的操作如加锁和解锁等 ,这样在函数执行开始时创建类对象 ,使用A a; 而不适A a();或 A()来创建, 在函数结束前会自动删除改对象 ,也就实现了开始时调用加锁操作 ,结束时调用解锁操作,俗称 RAII(资源获取即初始化)!

65.复制auto_ptr 模板实例化对象将指向的对象的控制权转移 ,然后把复制源设为空!

66.永远不要把auto_ptr 实例化的类型作为 STL容器的基本类型!

67.不要将auto_ptr 对象作为函数参数按值传递 ,会清空原有对象,造成不可预知的错误!

68.不要在虚函数中提供参数的默认初始化物!

69.访问层级(public protected private) 对重写虚函数没有任何影响 ,即使public 继承,你也可以将继承过来的本来应该是 public的函数写到private 作用域中 ,完全可以!

70.派生类中对基类中的非虚函数的重写或重载其实是遮掩 ,会将基类中同名的所有虚函数和非虚函数全部遮掩 ,使之无效, 这时想要构成重载 ,必须使用using A::fun() 函数来导入基类中 fun函数!

71.重载必须在同一个类作用域下才构成重载 ,否则只是遮掩!

72.重载虚函数要么对基类中的每一个都重写要么一个都不要重写 ,或者使用using A::fun() !

9159.com,73.C++中尽量避免使用指针,而是使用引用!

74.复制操作不经由模板成员函数来实现 ,必须显示给出复制操作的实现!

75.用户自定义版本的后置式形式自增自减运算符应该返回常量 ,因为后置后置不能作为左值!

76.前置式总是优于后置式,即 ++i总是优于i++ !

77.非成员友员允许在第一个参数上施行类型转换 ,而成员函数不能在第一个参数上施行类型转换!

78.在进行指针重新复制时一定要注意是否可能造成内存泄漏 ,是否要先释放当前指针所指内存空间!

79.mutable变量可以在const 函数中被修改 ,其效果好于const_cast<>, 所以尽量使用 mutable!

80.类重载运算符时有时必须参数和函数都是 const,这样保证在其他函数调用时即使传递常量参数也没问题!

81.变量传递给常量参数可以 ,但是常量传递给变量参数却不行!

82.多使用虚函数实现不同的功能 ,把基类尽量细分成更小的基类!

83.使用动态绑定而不是条件式的分派实现类型相关的需求!

84.如果某个类型可能成为基类 ,则一开始就把它写成抽象基类!

85.以public 方式继承的基类一般应该是抽象的 ,应该集中精力于接口继承而不是代码复用!

86.接口类就是没有数据成员 ,析构函数声明为虚函数,普通成员函数皆为纯虚函数 ,不声明构造函数的类型!

87.要么public, 要么友元函数 ,其它如protected 继承后的函数交叉调用可能会出现问题!

88.尽量不使用class 数组,多用 STL容器, 如vector,而且容器类型是指针而不是对象 ,如vector<B *>!

89.wget w1 = w2;调用拷贝构造函数,而 wget w1;w1 = w2;调用的是类赋值运算符!

90.类参数传值传递是调用拷贝构造函数 ,多用const 引用!

91.enum{star=5};这里定义的star 可以当作常量字面量来用 ,和#define star 5 效果是一样的!

92.尽量使用const,enum,inline 来代替#define,使用模板 inline函数代替宏!

93.对于单纯常量,最好用 const和enum 代替#define,对于形似函数的宏 ,最好使用inline 函数来替代!

94.如果const 出现在左边则所指的是常量 ,如果const 出现在右边 ,则指针是常量!

95.STL中const vector<int>::iterator 相当于Tconst,vector<int>::const_iterator相当于const T

96.函数的const 版本可以和原版本重载 ,用非const 函数调用 const函数可以减少代码重复!

97.使用函数返回静态对象将 non-local static对象转化为locat static 对象!

98.引用的赋值相当于把等号右边别名所指的对象值替换了等号左边别名所指对象的值,还是 2个对象!

99.可以通过声明纯虚析构函数来定义一个抽象类 ,这时纯虚析构函数必须给出定义才行!

100.析构函数绝对不要吐出异常 ,即使出现异常也要在析构函数内部处理 ,要么结束要么吞下!

101.不要在构造函数和析构函数中调用 virtual函数, 不会下降到 derived class类别, 用向上传递参数替换!

102.令赋值操作符返回一个reference to *this !

103.派生类中的拷贝构造函数和赋值符号不会自动拷贝或赋值基类部分 ,所以要显示调用基类拷贝或赋值函数!

104.在释放内存空间时先把原指针所指内存区域备份 ,再删除或指向新的内存空间 ,再delete 原来备份的区域!

105.多使用tr1::shared_ptr 和auto_ptr智能指针来自动释放内存空间!

106.类中尽量不要定义类型转换符号 ,即使定义也没有返回类型 ,因为类型转换符本身已经规定了返回类型!

107.shared_ptr对象如果有多个指向一个指针 ,则只有第一个需要使用指针初始化 ,其他的要么用拷贝构造函数 ,要么用赋值运算符初始化 ,指针初始化只能用一次!

108.对于内置类型、STL和函数对象 ,传值比较高效,但是对于其它类型 ,传递常量引用比较高效!

109.引用和指针一样支持多态性 ,因为引用的内部就是通过指针实现的!

110.尽量用non-member 和non-friend函数替换 member函数!

111.如果一个函数和类相关,但不是成员函数 ,那么该函数也不一定非得是友元函数 ,如果函数能通过类的公共接口完成功能 ,则完全不必声明为友元函数 ,但该函数返回值一般是const!

112.构造函数如果不是explicit则可以进行隐式类型转换 ,不管构造函数有几个参数 ,但前提是如果你给的实际参数个数小于构造函数需求参数个数 ,你得保证构造函数有默认构造参数!

113.一个类内对象内部函数可以访问对象自己的私有成员变量 ,但是如果有一个同类的另一个对象作为函数的参数 ,则该内部函数也可以访问另一个对象的私有成员变量!

114.尽量往后定义变量的出现 ,最好能等到变量不仅需要被使用而且初值也确定时再定义!

115.尽量避免使用转型,即使必须使用也得使用 C++特定的如static_cast 等!

116.虚析构函数都是public,没有其它的像 private和protected 类型的!

117.根据实际需要选准模式,是 is-a 还是has-a,private 继承和has-a类似 ,但是一般都是会选择has-a!

118.因为private 继承不是 is-a关系, 所以不能满足基类指针指向派生类的情况 ,当然不能使用多态性,只能看作是和 has-a一样的情况了!

119.virtual函数即使是private 函数且被 private继承, 虽然对于派生类不可访问 ,但派生类还是可以继承基类 virtual函数并重写的,并无影响!

120.指针可以改变其指向的对象 ,但是引用不行,引用一旦赋值后不能改变!

121.重载某个操作符时应该返回引用而不是指针!

122.隐式转换最多只能转换一次 ,超过一次就被禁止!

123.前缀返回引用,后缀返回 const value,后缀通过前缀实现,前缀效率比后缀高!

124.在析构函数中释放资源,尽量使用引用来捕捉异常 ,而不用传值或指针!

125.模板和异常规格不要混合使用 ,异常规格是一个应该被审慎使用的特性!

126.STL中对于iterator 尽量运用 (*iterator).first来取值, 而不是用 ->来取值!

127.C++禁止为非常量引用创建临时变量 ,所以非常量引用传递参数时不会发生隐式类型转换!

128.常量引用是会创建临时变量的 ,这时会发生隐式类型转换!

129.每一个重载运算符必须自带至少一个用户自定义类型的参数!

130.操作符 -> 优先级高于 * !

131.每种类有一个vtbl,每个对象有一个 vptr,RTTI是在vtbl 中增加一项 ,所以只会增加类大小,而不会增加对象大小!

132.析构函数必须被定义!

133.auto_ptr对象最好使用const引用传递 ,而不要用值传递!

134.编译器只能默认帮你进行一次类型转换 ,超过一次就不行!

135.对灵巧指针绝对不要提供一个转换到原始指针类型的转换操作符!

136.当使用类型转换太麻烦时 ,不妨就使用模板吧!

137.一定要为含有指针的类提供深拷贝构造函数 ,以免在以后的运用中出现错误!

138.构造函数和析构函数可以被子类继承 ,但如果析构函数是虚函数 ,继承的子类的析构函数也默认是虚函数 ,但你最好加上virtual增加可读性!

139.cout<<setiosflags(ios::fixed)<<setprecision(n)<<s1<<endl; 用来设置 C++中输出小数点后位数!

140.使用extern “C” 可以将函数变成 c函数风格, 即obj文件中不能进行名变换!

141.将十进制化为二进制或判断能否被 2整除或者除以2可以使用右移操作和 &1操作!

142.C++和C语言中,把整数赋值给字符变量,是将整数当作ASCII码赋给字符变量,将字符变量赋值给整数也是将字符变量对应的ASCII码赋给整数!

143.C++中STL容器的工作方式是对内建类型是位拷贝,自定义对象是存入对象的拷贝,使用insert或是push_back时都是使用拷贝,如果创建对象时是在堆中,则传指针给STL,如果在栈中,则传递对象本身!

144.C++中使用STL容器时,若对象拷贝动作较多,基类又要记录派生类,则存放指针,若是基本类型或者很少拷贝,则存放对象!

本文由9159.com发布于编程,转载请注明出处:3.静态局部变量直到程序终止时才退出,C++支持多

关键词:

上一篇:没有了
下一篇:没有了