The C++ Programming Language

Some Useful notes

Const

The difference between C++ and C:

In C, constant values default to external linkage, so they can appear only in source files. In C++, constant values default to internallinkage, which allows them to appear in header files.

When you declare a variable as const in a C source code file, you do so as:

const int i = 2;

You can then use this variable in another module as follows:

extern const int i;

But to get the same behavior in C++, you must declare your const variable as:

extern const int i = 2;

For objects that are declared as const, you can only call constant member functions. You can call either constant or nonconstant member functions for a nonconstant object. You can also overload a member function using the const keyword; this allows a different version of the function to be called for constant and nonconstant objects.

Chapter 1: Overview

Some tricks in c may seem unnecessary in C++.

Advice

Hint

  • Avoid use macros, use const and enum instead.
  • Don’t declare a variable before needs.
  • Use new and delete instead of malloc and free.
  • Use string and vector instead of cstring and array.
  • Use double instead of float.
  • Use namespace to avoid name crash.

Chapter 2: Tour of C++

Useful Notes

Note

In C++, arrays can declare as const expression length.

关于使用指针和引用:使用指针和引用是为了能够不复制对象, 一般指针用于处理需要修改对象的情形,而引用一般使用常引用, 不会修改被引用的对象。不过这个规则对于类似与Java这样的没有指针的语言就不成立, 它对于对象都是引用。

Class hierarchies and abstract class 是两个不同的概念, 前者侧重于类的重用,后者侧重于多态性。综合两者,可以实现抽象工厂的设计模式。

Templates are a compile-time mechanism so that their use incurs no run-time overhead compared to “hand-written code”.

注意string类型的c_str()函数返回的是当前string的指针,有可能当前对象是一个临时对象, 所以尽量不要使用c_str()。

You don’t have to know every detail of C++ to write good programs.

Chapter 4: C++ Basics

A float point literal is of type double.

Note a enum’s range, and an enum type can’t be initialized out of range.

If no initializer is specified, a global, namespace, or local static object is initialized to 0, while local vairables and objects created on the free store are not initialized. The same rule applies to class, static member are initialized by default while for normal member, only class type member are initialized by default contructor, built in types are not initialized.

no “implicit int” rule in C++, which is different from C.

合法的名字:只能有数字,字母,下划线组成,只能由字母开头。

C和C++一样有块级作用域,只是不能在循环中声明变量罢了。

不能在函数中再去定义和参数同名的变量。

Chapter 5: Pointers, Arrays, and Structures

The initializer for a “plain” T& must be an lvalue of type T. But for rvalue, can use const reference, for example:

const int & ref = 0;

为了避免拷贝,可以把指针和引用作为函数参数,如果需要改变这个参数, 那么传指针,否则传常引用比较方便。

类型在被使用前必须先被声明,注意下面的代码:

struct List; //因为在定义Link时使用了List,先在这里声明

struct Link {
    Link * next; //注意这里是指针,不用先声明,因为指针是integral value
    List * member_of;
};

struct List {...};

Chapter 6: Expressions

注意 cin.putback(ch); 以及在C中的 ungetc.

四种cast:

static_cast:
pointer type of same class hierarchy, enum to int, float to int. type may be checked when use static_cast
reinterpret_cast:
pointer of unrelated type and type unrelated, none type check.
const_cast:
Apparently.
dynamic_cast:
At run time, convert pointer of base type to derived type.

Chapter 7: Functions

Implicit type conversion may take place when arguments passing.

A void function can return a call of a void function.

Note

Function Overload

函数重载的处理方式:判断实际参数转换到这个重载函数的级别, 级别最低的函数被调用,如果两个函数级别最低,则会报错(编译型错误)。

转换等级为:

  1. Exact Match: no conversion.
  2. Match using promotions: integral promotions(bool, char, short to int), and float to double.
  3. Standard conversion: int to double, double to int, Derived* to Base*, T* to void*, int to unsigned int.
  4. user-defined conversions.

Functions declared in different non-space scopes do not overload. For example:

void f(int);

void g()
{
    void f(double);
    f(1); // call f(double)
}

Chapter 8 & 9: Namespace and Source Files

通过 using 来引入其他namespace的功能:

using Lexer::get_token;

An inline function must be defined - by identical definitions - in every translation unit in which it is used. 如果在头文件中定义了 inline function那么,引用它的源文件都会获得一份同样的定义。 所以一般在头文中中定义内联函数。

By default, consts and typedefs have internal linkage.

什么应该放在源文件中:(知道这个也就知道什么应该被放在头文件中)

  • 普通函数定义(区别内联函数)
  • 数据定义: int a;
  • 数组等聚合类型的数据定义 int tbl[] = {1, 2, 3};

如果模块a要使用模块b的全局数据:

  1. 在模块b的头文件中声明这个数据,如果模块b是namespace, 那么通过namespace声明
  2. 在模块b的源文件中定义这个数据
  3. 模块a的源文件include模块b的头文件

Chapter 10: Classes

Class Inline function

A function defined in the body of a class declaration is an inline function. If a function isn’t define in the body of a class declartion, it can be defined as inline explicitly.

class Test
{
public:
    int a() { return 1; }
    int b();
};

inline int Test::b()
{
    return 2;
}

In the above example, both a and b are inline functions. Note: b can be declare as inline expilictly. inilne int b();

Physical and Logical Constness

如果一个成员函数被声明为const,那么它不会改变当前对象的状态, 但这并不意味着它不能改变对象的属性,可以把这些属性声明为 mutable, 这样的场景在cache中很常见。

Constructor and deconstrutor

注意copy initialization 和 copy assignment:

Table t1;
Table t2 = t1; // copy initialization
Table t3;
t3 = t2; // copy assignment

构造和析构的顺序:

  1. 在同一类中,定义在前的先被构造
  2. 在同一个函数中,定义在前的先被构造
  3. 先初始化基类,再初始化成员,最后初始化当前类
  4. 析构与构造顺序相反

注意这个用法: X * p = new(buf) X;

Chapter 12: Derived Classes

注意虚函数和虚析构函数。 使用虚析构函数是为了使用基类的指针去析构继承类。

注意抽象工厂的设计。多多看看设计模式。

Chapter 13: Templates

注意模板是一种编译型的特性。模块会在编译时生成各种函数。 为了防止生成生成太多的代码,可以考虑对模板在对于指针类型时进行specification.

通过 template<> class Vector<void*> 进行specification, 然后可以通过 template <class T> class Vector<T*>: private Vector<void*> 让它对于所有的pointer都成立,注意它和直接定义 template<class T> class Vector<T*> 的区别。