Thinking in C++ learning(4)----- summary
Posted on 2007-03-05 16:01 Teddy Yan 阅读(146) 评论(0) 编辑 收藏 举报
1.值替代
const 和 define比有类型检查
2.指针
指向const的指针
const int* u
int const* u
const指针
int* const w;
int d=1;
const int* const x = &d;
int const* const x2 = &d;
现在,指针和对象都不能改变
3.函数和返回值
传递const值
void f1(const int i){
i++; //illegal -- compile-time error
}
返回const值
const int g();
对于内部类型(int, char)来说,按值返回的是否是一个const,是无关紧要的,所以应该去掉
当用户处理自定义的class,按值返回常量是很重要的
传递和返回地址
4.类
只能在构造函数里进行const变量的付值
4.1 构造函数初始化列表
4.2 内部类型的“构造函数”
float pi(3.14);
4.3 const对象和成员函数
如果声明一个对象是const,这样这个整个对象就不能被修改。如果把成员函数设置成const,那么这个函数就不能修改成员变量。不
仅要在声明的时候在函数的最后加const,而且在函数的定义也要加上
class Z {
int i;
mutable int j;
public:
Z();
void f() const;
};
Z:Z() : i(0), j(0) {}
void Z::f() const {
//!i++; // error -- const member function
j++;
}
volatile 在编译器认识的范围外,这个数据可以被改变
内联函数
宏的问题
任何在类中定义的函数自动地成为内联函数,但也可以在非类的函数前面加上inline关键字使之有效,必须使函数体和声明结合在一
起,否则,编译器将它作为普通函数对待。
因为类内部的内联函数节省了在外部定义成员函数的额外开销,所以我们一定想在类声明内每一处都使用内联函数。但函数较大,会使代码膨胀
访问函数(get,set)
内联函数和编译器
任何种类的循环都被认为太复杂而不扩展为内联函数。
要显式的或者隐式的取函数地址,编译器也不能执行内联
名字控制
static如何控制存储和可见性,通过c++的名字空间特征来访问名字的改进方法
static的两种含义,
1)在固定的地址上进行存储分配,也就是说对象是在一个特殊的静态数据区(static data area)上创建的,而不是每次函数调用时
在堆栈上产生的。
2)对一个特定的编译单位来说是局部的(c++仅限于类的范围)。这样,这个名字在这个单元或类之外是不可见的
静态变量即使没有初始化,编译器也会初始化为0
静态对象的析构函数在exit()时候被调用,所以析构函数内不要调用exit()
控制连接
一般情况下,在文件作用域(file scope)内的所有名字(即不被嵌套在类或者函数中的名字)对程序中的所有编译单元来说都是可见的
。这就是external linkage,例如全局变量和普通函数都有外部连接。
如果用static声明了,那就是internal linkage。只有这个文件作用域内,是可以访问的. extern 相反
名字空间
namespace NX {
class Y {
static int i;
public:
void f();
};
class Z;
void func();
}
int X::Y::i = 9;
namespace NY {
using namespace NX; //Using directive
using NX:func; //Using declaration
Y y;
}
C++中的静态成员
1.定义静态数据成员的存储
class A {
static int i;
public:
// ...
}
之后,必须在定义文件中为静态数据成员定义存储区
int A::i = 1;
2.静态成员函数
class X {
public:
static void f(){};
};
int main() {
X::f();
}
静态成员函数不能访问一般的数据成员,只能访问静态数据成员,也只能调用其他的静态成员函数
静态初始化的相依性
extern int y;
int x=y+1;
在另一个文件
extern int x;
int y=x+1;
替代连接说明
extern "C" float f(int a, char b);
这样函数f在编译时期,就不会因为重载而改变函数的名字
引用和拷贝构造函数
编译器要使用拷贝构造函数通过按值传递(by value)的方式在函数中传递和返回对象
c++中的引用
引用(&)就像能自动地被编译器间接引用的常量型指针。reference 必须有初始值,一旦一个引用被初始化为指向一个对象,他就不
能改变为另一个对象的引用。
为什么不能像内置类型一样,按值传递自定义对象
要返回自定义对象,自定义对象必须作为函数参数入栈---函数调用栈框架需要, C++和C支持中断,所以如果返回的时候是放在返回
地址的下面。这样,返回值可能会被修改。(与把返回值放到全局一样)。
为什么需要拷贝构造函数
按bitwise拷贝达不到复制对象的目的。需要重入---自己写构造函数
指向成员的指针
int ObjectClass::*pointerToMember;
定义一个名字为pointerToMember的成员指针,该指针可以指向在ObjectClass类中的任一int类型的成员
int ObjectClass::*pointerToMember = &ObjectClass::a;
class Simple2 {
public:
int f(float) const { return 1;}
};
int (Simple::*fp) (float) const;
int (Simple::*fp2) (float) const = &Simple2::f;
int main(){
fp = &Simple2::f;
}
多态性和虚函数
为什么传递参数要用指针或者引用,而不能直接传递对象?
为什么虚函数这么好,还要用关键字指出呢?因为,它影响效率。只要基类中的方法定义为virtual,所有子类也都是virtual了
什么是纯虚函数?为什么需要纯虚函数
实现公共接口,基类成为接口
纯抽象类?
什么是对象切片?
当向上类型转换的时候,会遇到对象切片。
构造函数对vtable的处理