1. 类中成员默认属性为private,private成员只对类里面的其他成员可见。
2. 在类里面定义的成员函数默认为inline函数。如果只是在类中声明,那么其定义也要有inline关键字,inline关键字在声明和定义处任意出现一次就行。inline函数的定义必须出现在头文件中。
3. 声明为const的成员函数不能改变调用它的对象的数据成员,const在声明和定义中都要写明。
4. data abstraction是指我们只知道接口(interface),不知道内部如何实现(implementation)。
5. encapsulation是指将低层次的元素组装成高层次的实体。例如一个函数,一个类,我们不知道它的内部是什么样的。
vector就是一个data abstraction和encapsulation的例子,array就不是。
好处:避免类内部出现无意的、可能破坏对象状态的用户及错误。
随时间推移可以根据需求改变或缺陷报告来完善类实现,而无须改变用户级代码。
6. 在类中,相同类型的成员变量可以写在一行。
private:
int age, height;
可以在类中使用类型别名
typedef stirng::size_type s_size;
类中的成员函数也可以重载。A class member function is unrelated to, and cannot overload, ordinary nonmember functions or functions declared in other classes.
7. 声明一个类,但不定义它,这称作前向声明(forward declaration),这个类是一个不完整类型(incomplete type).
8. 由于一个类在类体完成之前是未被定义的,所以在这个类中不能有这个类的对象。由于类名已经出现了,所以可以看做这个类已经生命了,所以可以使用指向该类对象的指针或者引用。
class LinkScreen {
Screen window;
LinkScreen *next;
LinkScreen *prev;
};
9. 成员函数的返回类型不总是在类区域里。如下例中,在get_cursor()函数定义中,在到达函数名之前,编译器并不识别index,所以必须写为Screen::index.
class Screen { public: typedef std::string::size_type index; index get_cursor() const; }; inline Screen::index Screen::get_cursor() const { return cursor; }
10. 构造函数的执行有两个过程:
- initialization phase,执行参数列表的初始化
- computation phase,即执行函数体内的代码
More important than the efficiency issue is the fact that some data members must be initialized.
We must use an initializer for any const or reference member or for any member of a class type that does not have a default constructor.
class ConstRef { public: ConstRef(int ii); private: int i; cont int ci; int &ri; }; //no explicit constructor initializer: error ri is uninitialized ConstRef::ConstRef(int ii) { i = ii; //OK ci = ii; //error: cannot assign to a const ri = i; //assigns to ri which was not bound to an object }
11. 像下面来写构造函数,一举两得
class Sales_item { public: Sales_item(const string &book = ""): isbn(book), units_sold(0), revenue(0.0) { } Sales_item(istream &is); };
12. 没有任何构造函数的话,编译器就会产生一个默认构造函数。一旦有一个构造函数,那么编译器就不会产生一个默认构造函数。
13. 只有一个参数的构造函数一般在声明处写上explicit关键字,拷贝构造函数除外。explicit关键字只能在声明处写。
14. A friend may be an ordinary, nonmember function, a member function of another previously defined class, or an entire class.
谁被声明为friend,证明谁有权限接触类中的成员。相反,类中的成员并不能接触friend中的东西。
15. Making the object global vilates encapsulation.
16. 对于类中的static成员,声明中必须带static,定义中不能带static。
对于static成员变量,也必须在源文件中定义一次,且只能定义一次。
static const [Integral Types] can be initialized in class body, but it must be defined outside the class defintion(PS: I tried in g++, it didn't need to do this). The definition of the member must not specify an initial value.
#include <iostream> using namespace std; class Account { public: Account(const string &s = "") : owner(s) { } static double get_rate(); static int get_years(); static void set_rate(double r) { interestRate = r; } private: string owner; static double interestRate; static const int years = 10; }; double Account::interestRate = 0.0; const int Account::years; double Account::get_rate() { return Account::interestRate; } int Account::get_years() { return years; } int main() { Account a; a.set_rate(1.0); cout << a.get_rate() << endl; cout << Account::get_years() << endl; return 0; }
#include <iostream> #include <vector> using namespace std; class A { public: A(int aa) { a = aa; cout << "invoked" << endl; } void print() { cout << a << endl; } private: int a; }; int main() { A a(4); //A a1; // no matched constructor //A a2(); // Only use () when a constructor accepts an parameter (without a default argument) a.print(); //a1.print(); int *p = new int(2); delete [] p; cout << *p << endl; vector<string> vec(5); vec.push_back("abc"); cout << vec.size() << endl; return 0; }