[原]C++:一些基础知识
2、Variable:有名字的Object。
3、static(不全,希望有大虾补全)
- 在函数中,表示该对象是由该函数所有的使用者共享的对象。
- 在类中,表示该对象是类对象,由所有该类的实例共享。因此没有this。
- 在编译单元中,表示该对象只在该编译单元内可见。
- 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。
- 用来保护对象不受修改。
- const對象只能調用const成員函數。
- const成员函数,只能访问const成员——当然不包括logical constness。
- const参数,表明该参数不可被函数修改,一般作用于T*或者T&。
- T * const和T const *(const T*)的区别。从右向左读就能明白区别。传参时,T * const与T*等价。还有const T * const,表明该对象以及其指向的对象都是read only的。
- const返回值:返回的对象是readonly的。
注:对于一个对象的const成员函数来说,有bitwise和logical的constness之分。logical的不多说,通过用mutable关键字修饰数据成员即可。而对于bitwise的,有一点需要注意:当类A包含B*数据成员,A的const成员函数只要不修改B*就不破坏bitwise的constness,也就是说,该成员指向的对象被修改不违背bitwise的constness。参考文章末尾的代码。
5、Scope:使名字有意义的一个区间。
6、Reference:对象的别名。定义时必须绑定一个对象,且绑定之后不能再绑定到另一个对象。相当于T* const。可以与lvalue和rvalue绑定。
7、Pointer:指针,只能指向具有lvalue的对象。
9、当参数类型是数组的引用时,数组大小是该类型的一部分。因此,void func(T (&array)[10]);参数类型是T[10]而不是T[]。
10、const成员函数中的const修饰的是*this。
11、数据、函数、typedef都可以作为一个类的成员。在类中可以有成员函数的声明和定义。对于普通的数据成员,只能有声明。
12、对于不完整类型,只能声明/定义该类型的指针。
13、在类外定义成员函数,返回类型和函数名都不在类的scope中,参数列表则在,所以需要用::来指名返回类型和函数名所属的scope。
14、没有默认构造函数的自定义类型的数据成员,以及const/reference成员必须在构造函数的初始化列表中初始化。初始化的顺序与其在类中声明顺序一致。因此应该注意初始化列表中不要存在依赖关系。
15、仅当类没有任何构造函数是,编译器才会为其生成一个默认构造函数。
16、直接初始化与拷贝初始化:T obj = T(); / T obj();都属于直接初始化。T obj = anotherT;是拷贝初始化。将调用拷贝构造函数。
17、带有一个参数的构造函数隐含了从参数类型到该类的一个类型转换。要禁用这种转换可以使用explicit关键字。
18、Friend机制使得非成员函数或类可以访问该类的私有成员。friendship不能被继承。
19、Rule of three:当一个类需要自定义析构函数,该类也一定需要自定义的“=”和拷贝构造函数。
20、当指向某个对象的指针离开其scope时,析构函数不会被自动调用。因此需要使用delete来达到目的。
21、修改对象状态的重载操作符必须是成员函数,因此=、++、--等操作符必须重载为成员。而[]、()、->也需要重载为成员。IO操作符必须重载为非成员,否则将出现obj<<cout或者obj>>cin之类的表达式,导致不一致。对于重载的->,必须返回一个指针或者重载了->的对象。因为obj->member可以写成:obj.operator->()->member。
22、仅当使用指向基类的引用或者指针调用虚函数时,动态绑定才会起作用。这是因为:class Base; class D: public Base; D aD; Base * p = &aD;这里,p有两个类型,一个是动态类型(D),一个是静态类型(Base)。当这两个类型吻合时,不需要做任何的动态绑定。而只用当这两个类型不吻合,才会有动态绑定的发生。
23、public表示所有的代码都可以访问;protected表示只有自己和派生类可以访问;private表示只有该类自己可以访问。public继承表示该类相当于派生类的public成员;protected继承表示该类相当于派生类的protected成员,private继承表示该类相当于派生类的private成员。
24、栈展开:在调用栈上反向查找异常处理器的过程。在此期间,函数的局部对象将被销毁。
25、typedef T * PT; const PT p;第二条语句表示p is a const PT(pointer to T)。
26、不想被作为多态基类使用的类一定不要声明virtual的析构函数。C++没有阻止类被继承的机制,因此随意继承一个类可能会带来意想不到的后果。
27、多重继承时,使用其中某个基类的指针或引用来调用虚函数时,只能调用属于该基类的虚函数接口。
28、类型转换时会产生一个临时副本。
29、通过函数指针来调用函数时,只能调用比函数指针声明中异常规格说明更严格或者同等严格的函数。虚函数也是如此。很好理解:宽松异常规格的函数可能会抛出调用方无法处理的异常。
PS:中间可能有些错误,请大虾指正!拍砖的可以,骂人的不要。
第4条的示例代码:
class B1
{
public:
B1(): m_Val(0) {};
void SetVal(int aVal) { m_Val = aVal; }
private:
int m_Val;
};
class A1
{
public:
A1(B1* aB1): m_b1(aB1) {}
~A1() { if (m_b1) delete m_b1; m_b1 = NULL;}
inline void ConstOrNonConst(int) const; // 注意!
private:
B1* m_b1;
};
void A1::ConstOrNonConst(int aVal) const // 没有打破bitwise的constness!
{
if (m_b1)
m_b1->SetVal(aVal); // 修改了m_b1所指对象!
}
参考:
C++ Primer, by Stanly.B.Lippman
Effective C++, by Scott Mayers
Copyleft (C) 2007-2009 raof01.
请保留此权利声明,并标明文章原始地址和作者信息