C++ Primer 读书笔记 - 第十五章
添加时间:2013-6-4 点击量:
1. OOP基于三个根蒂根基概念 - data abstraction,inheritance,dynamic binding. 其关键思惟是多态性(polymorphism)。
2. 定义为virtual的函数是基类等待派生类从头定义的,基类派生类持续的函数不克不及定义为虚函数。
3. virtual关键字只能呈如今类体内的声明中,不克不及呈如今类体外的定义中。
4. 派生类只能经由过程派生类对象接见其基类的protected成员,派生类对其基类类型对象的protected成员没有特别接见权限。
void Bulk_item::memfcn(const Bulk_item &d, const Item_base &b)
{
//attempt to use protected member
double ret = price; //ok: uses this->price
ret = d.price; //ok: uses price a Bulk_item object
ret = b.price; //error: no access to price an Item_base
}
5. 子类持续了基类的所有成员,但对private成员没有接见权限。
6. 派生类一般会重定义所持续的虚函数,若是派生类没有重定义某个虚函数,则应用基类中定义的版本。
7. 派生类中虚函数的声明必须与基类中的定义体式格式完全匹配,但有一个例外:返回对基类型的引用(或指针)的虚函数。派生类中的虚函数可以返回基类函数所返回类型的派生类的引用(或指针)。
8. 一旦函数在基类中声明为虚函数,它就一向为虚函数,派生类无法改变该函数为虚函数这一事实。派生类重定义虚函数时,可以应用virtual关键字,但不是必须如许做。
9. 一个类在被当做基类应用之前,必须已经定义过。
10. C++中的函数调用默认不实用动态绑定。要触策动态绑定,必须满足两个前提:
- 只有指定为虚函数的成员函数才干进步履态绑定,成员函数默认为非虚函数,非虚函数不进步履态绑定。
- 必须经由过程基类类型的引用或指针进行函数调用。
11. static type at compile time, dynamic type at run time.
12. 应用scope operator 来覆盖virtual mechanism
Item_base basep = &derived;
double d = basep->Item_base::net_price(42);
13. Friendship does not inherit.
14. 若是基类定义了static成员,则全部持续层次中只有一个如许的成员。无论从基类派生出几许个派生类,每个static成员只有一个实例。
15. 基类到派生类的转换:
Item_base base;
Bulk_item bulkp = &base; //error: cannot convert base to derived
Bulk_item &bulkRef = base; //error: cannot convert base to derived
Bulk_item bulk = base; //error: cannot convert base to derived
Bulk_item bulk;
Item_base itemp = &bulk; //OK: dynamic type is Bulk_item
Bulk_item bulkp = itemp; //error: cannot convert base to derived
16. Constructors and the copy-control members are not inherited.
17. 派生类机关函数的写法:
class Disc_item : public Item_base {
public:
Disc_item(const string &book = , double sales_price = 0.0,
size_t qty = 0, double disc_rate = 0.0) :
Item_base(book, sales_price),
quantity(qty), discount(disc_rate) { }
protected:
size_t quantity;
double discount;
};
18. 每个析构函数只负责清理本身的成员。
19. 像其他虚函数一样,析构函数的虚函数性质都将持续。是以,若是层次中根类的析构函数为虚函数,则派生类析构函数也将是虚函数,无论派生类显示定义析构函数还是应用合成析构函数,派生类析构函数都是虚函数。
20. 原始基类的析构函数应当定义为virtual,即使它什么事都不做。
21. 若是在机关函数或析构函数中调用虚函数,则运行的是为机关函数或析构函数自身类型定义的版本。
22. 在编译时代,编译器会把所有类型当成静态类型,然后查找函数名。若是一个函数仅在派生类中定义了,用基类的指针是找不到它的,会产生编译错误。
23. The base class functions are considered only if the derived does not define the function at all.
24. 虚拟函数及感化域
#include <iostream>
using namespace std;
class Base {
public:
virtual void fcn() { cout << Base::fcn() << endl; };
};
class D1 : public Base {
public:
//hide fcn in the base; this fcn is not virtual
void fcn(int p) { cout << D1:fcn(int) << endl; } //parameter list differs fcn in Base
void fcn(int a, int b) { cout << D1::fcn(int, int) << endl; }
//D1 inherits definition of Base::fcn(), but it cannot be called a D1 object
};
class D2 : public D1 {
public:
void fcn(int p) { cout << D2::fcn(int) << endl; } //nonvirtual function hides D1::fcn(int)
void fcn() { cout << D2::fcn() << endl; } //redefines virtual fcn Base
};
int main()
{
Base bobj;
D1 d1obj;
D2 d2obj;
Base bp1 = &bobj;
Base bp2 = &d1obj;
Base bp3 = &d2obj;
bp1->fcn();
bp2->fcn();
bp3->fcn();
D1 dd1 = &d1obj;
((Base)dd1)->fcn();
dd1->fcn(); //error
d1obj.fcn(); //error
return 0;
}
25. 在函数形参表后面写上=0以指定纯虚函数,发明抽象基类(abstract base class)会产生编译错误。
26. A class containing(or inheriting)one or more pure virtual functions is an abstract base class. We may not create objects of an abstract type except as parts of objects of classes derived the abstract base.
27. 两个编程例子
文艺不是炫耀,不是花哨空洞的文字堆砌,不是一张又一张的逆光照片,不是将旅行的意义转化为名牌包和明信片的物质展示;很多时候它甚至完全不美——它嘶吼、扭曲,它会痛苦地抽搐,它常常无言地沉默。——艾小柯《文艺是一种信仰》
1. OOP基于三个根蒂根基概念 - data abstraction,inheritance,dynamic binding. 其关键思惟是多态性(polymorphism)。
2. 定义为virtual的函数是基类等待派生类从头定义的,基类派生类持续的函数不克不及定义为虚函数。
3. virtual关键字只能呈如今类体内的声明中,不克不及呈如今类体外的定义中。
4. 派生类只能经由过程派生类对象接见其基类的protected成员,派生类对其基类类型对象的protected成员没有特别接见权限。
void Bulk_item::memfcn(const Bulk_item &d, const Item_base &b)
{
//attempt to use protected member
double ret = price; //ok: uses this->price
ret = d.price; //ok: uses price a Bulk_item object
ret = b.price; //error: no access to price an Item_base
}
5. 子类持续了基类的所有成员,但对private成员没有接见权限。
6. 派生类一般会重定义所持续的虚函数,若是派生类没有重定义某个虚函数,则应用基类中定义的版本。
7. 派生类中虚函数的声明必须与基类中的定义体式格式完全匹配,但有一个例外:返回对基类型的引用(或指针)的虚函数。派生类中的虚函数可以返回基类函数所返回类型的派生类的引用(或指针)。
8. 一旦函数在基类中声明为虚函数,它就一向为虚函数,派生类无法改变该函数为虚函数这一事实。派生类重定义虚函数时,可以应用virtual关键字,但不是必须如许做。
9. 一个类在被当做基类应用之前,必须已经定义过。
10. C++中的函数调用默认不实用动态绑定。要触策动态绑定,必须满足两个前提:
- 只有指定为虚函数的成员函数才干进步履态绑定,成员函数默认为非虚函数,非虚函数不进步履态绑定。
- 必须经由过程基类类型的引用或指针进行函数调用。
11. static type at compile time, dynamic type at run time.
12. 应用scope operator 来覆盖virtual mechanism
Item_base basep = &derived;
double d = basep->Item_base::net_price(42);
13. Friendship does not inherit.
14. 若是基类定义了static成员,则全部持续层次中只有一个如许的成员。无论从基类派生出几许个派生类,每个static成员只有一个实例。
15. 基类到派生类的转换:
Item_base base;
Bulk_item bulkp = &base; //error: cannot convert base to derived
Bulk_item &bulkRef = base; //error: cannot convert base to derived
Bulk_item bulk = base; //error: cannot convert base to derived
Bulk_item bulk;
Item_base itemp = &bulk; //OK: dynamic type is Bulk_item
Bulk_item bulkp = itemp; //error: cannot convert base to derived
16. Constructors and the copy-control members are not inherited.
17. 派生类机关函数的写法:
class Disc_item : public Item_base {
public:
Disc_item(const string &book = , double sales_price = 0.0,
size_t qty = 0, double disc_rate = 0.0) :
Item_base(book, sales_price),
quantity(qty), discount(disc_rate) { }
protected:
size_t quantity;
double discount;
};
18. 每个析构函数只负责清理本身的成员。
19. 像其他虚函数一样,析构函数的虚函数性质都将持续。是以,若是层次中根类的析构函数为虚函数,则派生类析构函数也将是虚函数,无论派生类显示定义析构函数还是应用合成析构函数,派生类析构函数都是虚函数。
20. 原始基类的析构函数应当定义为virtual,即使它什么事都不做。
21. 若是在机关函数或析构函数中调用虚函数,则运行的是为机关函数或析构函数自身类型定义的版本。
22. 在编译时代,编译器会把所有类型当成静态类型,然后查找函数名。若是一个函数仅在派生类中定义了,用基类的指针是找不到它的,会产生编译错误。
23. The base class functions are considered only if the derived does not define the function at all.
24. 虚拟函数及感化域
#include <iostream>
using namespace std;
class Base {
public:
virtual void fcn() { cout << Base::fcn() << endl; };
};
class D1 : public Base {
public:
//hide fcn in the base; this fcn is not virtual
void fcn(int p) { cout << D1:fcn(int) << endl; } //parameter list differs fcn in Base
void fcn(int a, int b) { cout << D1::fcn(int, int) << endl; }
//D1 inherits definition of Base::fcn(), but it cannot be called a D1 object
};
class D2 : public D1 {
public:
void fcn(int p) { cout << D2::fcn(int) << endl; } //nonvirtual function hides D1::fcn(int)
void fcn() { cout << D2::fcn() << endl; } //redefines virtual fcn Base
};
int main()
{
Base bobj;
D1 d1obj;
D2 d2obj;
Base bp1 = &bobj;
Base bp2 = &d1obj;
Base bp3 = &d2obj;
bp1->fcn();
bp2->fcn();
bp3->fcn();
D1 dd1 = &d1obj;
((Base)dd1)->fcn();
dd1->fcn(); //error
d1obj.fcn(); //error
return 0;
}
25. 在函数形参表后面写上=0以指定纯虚函数,发明抽象基类(abstract base class)会产生编译错误。
26. A class containing(or inheriting)one or more pure virtual functions is an abstract base class. We may not create objects of an abstract type except as parts of objects of classes derived the abstract base.
27. 两个编程例子
文艺不是炫耀,不是花哨空洞的文字堆砌,不是一张又一张的逆光照片,不是将旅行的意义转化为名牌包和明信片的物质展示;很多时候它甚至完全不美——它嘶吼、扭曲,它会痛苦地抽搐,它常常无言地沉默。——艾小柯《文艺是一种信仰》