C语言中级编程之个人查缺补漏

个人C++注意点(查漏补缺)(2008-10-25):

1、A[0]
它是一个表达式,而不是一个名字:(A+0)

2、通过初始化列表赋初值:
int a[2]={int(1),int(2)};

3、前置声明只能用于引用和指针,不能用于对象


4、构造函数天然具有类型转换功能,除非用explicit关闭

 

5、指针的引用
 int *p;
 int *&q=p;
 但引用不能再有引用。

6、针对函数返回指针一定要特加注意;
 解决办法一:
  static char p[] = "hello word";
  return p;
  静态变量是在全局变量区域的
  全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,
  初始化的全局变量和静态变量在一块区域,
  未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
  - 程序结束后有系统释放

 解决办法二:
  全局变量的方式
 解决办法三:
  const char *p="hello word";
  return p;
  //常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
 解决办法四:
  堆空间

7、int a[4]={1};
 

8、声明指向成员的指针

 声明指向公有数据成员的指针
类型说明符(类名::*指针名);

 声明指向公有函数成员的指针
类型说明符(类名::*指针名)(参数表);

 对指向数据成员的指针赋值:
  指针名=&类名::数据成员名;


 通过对象名(或对象指针)与成员指针联
 – 手来访问数据成员
  对象名.* 类成员指针名
   或:
  对象指针名—>*类成员指针名

 指向函数成员的指针
赋值

– 指针名=类名::函数成员名;

– 通过对象名(或对象指针)与成员指针
结合来访问函数成员
(对象名.* 类成员指针名)(参数表)
或:
(对象指针名—>*类成员指针名)(参数表)

 

9、Point &r = *(new Point(2,4));
 delete &r;

 


10、类的聚集中的浅拷贝,深拷贝(改赋值函数和拷贝构造函数)。
 (对象计数器的使用)
 赋值运算函数应该考虑:是否为自赋值;
 
11、私有继承的时候
 可以用using 类型名::的语法“打捞”出来----回归到原来的级别
 注意: 1、不能区分重载,有重载的全部“打捞“出来
  2、只能还原,不能提高访问级别
  3、只能还原直接基类,不能“隔代”打捞
  4、不能让子孙类重复“打捞”
12、必须用初始化列表的地方
  1、继承
  2、组合
  3、引用
  4、常数据成员
 此处注意静态数据成员的内外初始化
 
13、初始化列表真正执行的顺序服从定义列表的顺序或继承列表的顺序

14、类型兼容千万别用在对象数组上
 1、用指针数组,而对象不放在数组中
 2、改用强类型的vector  vector<B *> vbp;

15、静态常数据成员相当于程序中的”常量“

16、静态数据成员属于类属性,而常数据成员属于对象属性

17、虚拟继承--调整指针--对象体积膨胀

18、不要用虚拟继承来分辨同名二义
 private继承来的和由public继承的两个同名函数,不能想当然的认为private继承来的不能访问而public继承来的可以访问
  就不造成二义

19、注意对齐
class base
{
 char x;
};
class A:virtual public base
{
 int a1;
};

class B:virtual public base
{
 int b1;
};

class C:public A,public B
{
 int c1;
};

void main()
{
 cout<<"sizeof(base):"<<sizeof(base)<<endl; //1
 cout<<"sizeof(A):"<<sizeof(A)<<endl;  //9 
 cout<<"sizeof(B):"<<sizeof(B)<<endl;  //9
 cout<<"sizeof(C):"<<sizeof(C)<<endl;  //21
}


20、静态数据成员 static int i;
 int A::i= 10; // 静态成员的初始化

21、内嵌类:class中有class的声明
 局部类:函数中有class的声明
 类的聚集:类的聚集描述的是一个类内嵌其他类的对象作为成员的情况,是包含与被包含的关系.
 类的组合:用一个类的对象作为另一个类的成员的时候,就是类的组合
 
22、返回常对象的函数,目的是防止返回值被作为左值赋值。 (a+b=c;)

23、"&&"," ||" 不能用于重载  (注意其特点 a&&b ,当a为假的时候b的值不会被计算,而用函数实现重载时会改变它这种特性)

24、Point a,b;
 Point c = a + b; //隐含调用 operator+ ,此时还会调用拷贝构造函数
 
 Point c;
  c = a + b ; //此时会调用赋值函数operator=   和   operator+
  
  显示调用为: c.operator=((a.operator+(b));


运算符成员函数的设计:
25、前置单目运算符重载函数Clock& Clock::operator ++() 必须返回一个引用型
 ++(++a);
 若返回一个对象而非引用,返回时该对象会拷贝到一个临时变量上,变成了这样:++(temp);  这样真正的a就只自加了一次

26、后置单目运算符重载Clock Clock::operator ++(int) 必须返回一个对象
 (a++).setTimer();  千万不要试图这样来修改一个对象的值,因为(a++)返回的只是一个副本
 
 //后置单目运算符重载
 Clock Clock::operator ++(int)
 { //注意形参表中的整型参数
  Clock old=*this;
  ++(*this); //调用了另一个成员函数
  return old;
 }

27、友元函数的Name和成员函数的Name一定不能相同

28、 运算符  使用形式  等价式
 双目运算符@  oprd1 @ oprd2   operator @(oprd1,oprd2 )
 前置单目@  @oprd    operator @( oprd )
 后置单目@  oprd @    operator @( oprd , 0 )

 


类型转换
29、三目运算符 a ? b : c
 不管a是真是假 b和c都会被转换为同一种类型


30、 构造函数放在private中,可以防止类型转换时的"外转内"

31、类型转换函数可以被继承

32、虚函数具有继承性。基类中声明了虚函数,派生类中无论是否说明,同原型的函数都自动为虚函数。

33、虚函数只能用于非静态非友元非内联的成员函数。虽然不可以是友元函数,但可以外派成为另一个类的友元函数。

34、虚函数的实现机制
  编译器发现某类含有虚函数,则对其生成的对象悄悄地加入一个void 型的指向指针的指针:vptr,
 并让其指向一个由类维护的虚函数表vtable(其实是个指针数组),每个表项是一个虚函数名(地址),
 排列次序按虚函数声明的次序排列。
  在类族中,无论是基类还是派生类,都拥有各自的vptr和vtable。相同类型所生成的对象共享了同
 数一个vtable。
  该项技术的实质是“将找谁变成到哪去找”——不用管找到的是哪一个。

35、

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值