Skip to content

Commit 7538c90

Browse files
committed
update many contents
1 parent 9cacd32 commit 7538c90

16 files changed

+272
-48
lines changed

C++/11_SmartPoint.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ int main()
334334

335335
# 更多阅读
336336

337+
[Top 10 dumb mistakes to avoid with C++ 11 smart pointers](http://www.acodersjourney.com/2016/05/top-10-dumb-mistakes-avoid-c-11-smart-pointers/)
337338
[C++ 引用计数技术及智能指针的简单实现](http://www.cnblogs.com/QG-whz/p/4777312.html)
338339
[从auto_ptr说起](http://www.jellythink.com/archives/673)
339340
[到C++11中的智能指针](http://www.jellythink.com/archives/684)

C++/Basic.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void main( void )
6161
Test a(1); // 定义了一个对象
6262
a.fun(); // 调用对象的函数
6363
Test b(); // 声明了一个函数
64-
b.fun(); // Error!!!
64+
// b.fun(); // Error!!!
6565
}
6666
```
6767

C++/Class.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ const float A::e = 5;
238238

239239
## 成员函数
240240

241-
成员函数也可以被重载,只要满足重载的要求,即`同一个作用域内`的几个`函数名字相同``形参列表`不同,成员函数的 virtual 关键字可有可无。此外要注意**const函数与同名的非const函数是重载函数**;const对象只能调用const函数 ,但是非const对象可以调用const函数。
241+
成员函数也可以被重载,只要满足重载的要求,即`同一个作用域内`的几个`函数名字相同``形参列表`不同,成员函数的 virtual 关键字可有可无。
242242

243243
[const函数的操作](http://www.nowcoder.com/questionTerminal/09ec766d373a43769603963664e231e7)
244244

@@ -253,6 +253,22 @@ const float A::e = 5;
253253
* 隐藏:用什么就调用什么。
254254
* 覆盖:调用派生类。
255255

256+
**C++中成员函数能否同时用static和const进行修饰?**
257+
258+
不行!这是因为C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的中参数的值,会在函数中添加一个隐式的参数`const this*`。但当一个成员为static的时候,该函数是没有this指针的,也就是说此时const的用法和static是冲突的。
259+
260+
更详细的解释如下:在定义一个类对象的时候,实际上只给该对象的非静态的数据成员分配内存空间(假设没有虚函数),而该类的静态成员数据以及该类的函数都在编译的时候分配到一个公共的空间里,所有,在定义一个对象并调用类对象的函数的时候,函数根本不知道到底是哪个对象调用了他,怎么解决这个问题呢?
261+
262+
C++利用传递this指针的方式来实现,调用一个类对象里的函数的时候,将把这个对象的指针传递给他,以便函数对该对象的数据进行操作,对于一个定义为const的函数,传递的是const的this指针,说明不能更改对象的属性,而对static成员的函数不传递this指针,所以不能用const来修饰static的成员函数了!
263+
264+
从对象模型上来说,类的非static成员函数在编译的时候都会扩展加上一个this参数,const的成员函数被要求不能修改this所指向的这个对象;而static函数编译的时候并不扩充加上this参数,自然无所谓const。
265+
266+
如果在编写const成员函数时,不慎**修改了数据成员,或调用了其他非const成员函数,编译器就会报错**。如果想在const函数中改变某个成员变量的值,那么可以将该变量声明为 mutable 类型。
267+
268+
此外,要注意**const函数与同名的非const函数是重载函数**,类的const对象只能调用const函数,非const对象可以调用const函数和非const成员函数。
269+
270+
具体的示例在 [C++_Class_Func.cpp](../Coding/C++_Class_Func.cpp)
271+
256272
# 继承
257273

258274
继承是类的重要特性。通过继承联系在一起的类构成一种层次关系,通常在层次关系的根部有一个基类,其他类则直接或者间接地从基类继承而来,这些继承得到的类称为派生类。基类负责定义在层次关系中所有类公同拥有的成员,而每个派生类定义各自特有的成员。
@@ -361,6 +377,7 @@ More Effective C++ 条款 27
361377
[深入理解C++的动态绑定和静态绑定](http://blog.csdn.net/chgaowei/article/details/6427731)
362378
[C++ 抽象类](http://www.cnblogs.com/balingybj/p/4771916.html)
363379
[关于C++中的虚拟继承的一些总结](http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/05/2537451.html)
380+
[类中的const成员](http://www.cnblogs.com/kaituorensheng/p/3244910.html)
364381
365382
366383
[1]: http://7xrlu9.com1.z0.glb.clouddn.com/C++_Class_1.png

C++/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ C++11修复大量缺陷和降低代码拖沓,比如lambda表达式的支持将
184184
《STL 源码剖析》
185185
《Effective C++》
186186
《More Effective C++》
187+
[C++ FAQ](https://isocpp.org/faq)
187188
[C++_More](More/C++_More.md)
188189
[C/C++内存管理详解](http://chenqx.github.io/2014/09/25/Cpp-Memory-Management/)
189190
[那些不能遗忘的知识点回顾——C/C++系列](http://www.cnblogs.com/webary/p/4754522.html)

C++/Template.md

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
使用模板的目的就是能够让`程序员编写与类型无关的代码`。比如编写了一个交换两个整型int 类型的swap函数,这个函数就只能实现int 型,对double,字符这些类型无法实现,要实现这些类型的交换就要重新编写另一个swap函数。使用模板的目的就是要让这程序的实现与类型无关,比如一个swap模板函数,即可以实现int 型,又可以实现double型的交换。
99

10-
注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。
10+
注意:**模板的声明或定义只能在全局,命名空间或类范围内进行。**即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。
1111

1212
# 函数模板
1313

@@ -76,7 +76,7 @@ public:
7676

7777
## 成员函数
7878

79-
类模板的成员函数可以在类模板的定义中定义(这样就是 inline函数),也可以在类模板定义之外定义。要注意的是类模板成员函数本身也是一个模板,类模板被实例化时它并不自动被实例化,只有当它被调用或取地址,才被实例化。
79+
类模板的**成员函数可以在类模板的定义中定义(这样就是 inline函数),也可以在类模板定义之外定义**。要注意的是类模板成员函数本身也是一个模板,类模板被实例化时它并不自动被实例化,只有当它被调用或取地址,才被实例化。
8080

8181
在类模板外部定义成员函数的方法为:
8282

@@ -92,7 +92,76 @@ void A<T1,T2>::h(){
9292
}
9393
```
9494

95-
**当在类外面定义类的成员时template后面的模板形参应与要定义的类的模板形参一致**
95+
`当在类外面定义类的成员时template后面的模板形参应与要定义的类的模板形参一致`
96+
97+
# 模板编译
98+
99+
当编译器遇到一个模板定义时,并不生成代码。只有当我们实例化出模版的一个特定版本时,编译器才会生成代码。
100+
101+
**模板的声明和实现是否一定要在同一个头文件中?**
102+
103+
要知道,我们在调用一个函数时,编译器只需要掌握函数的声明。类似的,当**我们使用一个类类型的对象时,类定义必须是可用的,但成员函数的定义不必已经出现**。因此,可以将**类定义和成员函数声明**放在头文件(.h)中,而普通函数和类的成员函数的定义放在源文件中(.cpp)。
104+
105+
这样就可以把源文件编译成目标文件打包成库,然后把库和头文件给客户使用。对客户来说,可以使用相应的功能,但是看不到源文件。这样可以很好地保护商业利益,此外如果想要更改实现的话,可以重新编译自己的库,客户不需要为此更改代码。
106+
107+
但是在使用模板时,这种习惯性做法将变得不再有用。因为**为了生成一个实例化版本,编译器必须要掌握函数模板或类模板成员函数的定义**。因此,与非模版代码不同,模板的头文件通常既包括声明也包括定义。一般做法就是将模板的声明和定义都放置在同一个.h文件中,这就是为什么所有的STL头文件都包含模板定义。
108+
109+
详细来解释的话,主要从这[三个方面](https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl)来理解:
110+
111+
1. A template is not a class or a function. A template is a “pattern” that the compiler uses to generate a family of classes or functions.
112+
2. In order for the compiler to generate the code, it must see both the template definition (not just declaration) and the specific types/whatever used to “fill in” the template. For example, if you’re trying to use a Foo<int>, the compiler must see both the Foo template and the fact that you’re trying to make a specific Foo<int>.
113+
3. Your compiler probably doesn’t remember the details of one .cpp file while it is compiling another .cpp file. It could, but most do not and if you are reading this FAQ, it almost definitely does not. BTW this is called the “`separate compilation model`.”
114+
115+
下面看一个例子,假设一个模板类 Foo 的声明如下:
116+
117+
```c++
118+
template<typename T>
119+
class Foo {
120+
public:
121+
Foo();
122+
void someMethod(T x);
123+
private:
124+
T x;
125+
};
126+
```
127+
128+
成员函数的定义如下:
129+
130+
```c++
131+
template<typename T>
132+
Foo<T>::Foo()
133+
{
134+
// ...
135+
}
136+
template<typename T>
137+
void Foo<T>::someMethod(T x)
138+
{
139+
// ...
140+
}
141+
```
142+
143+
现在假设在 `Bar.cpp` 中使用 `Foo<int>`:
144+
145+
```c++
146+
// Bar.cpp
147+
void blah_blah_blah()
148+
{
149+
// ...
150+
Foo<int> f;
151+
f.someMethod(5);
152+
// ...
153+
}
154+
```
155+
156+
如果我们将Foo 的构造函数以及someMethod成员函数的定义放在Foo.cpp中,编译时会出现链接错误。这是因为编译器在编译 Foo.cpp 时知道了模版的定义代码,在编译 Bar.cpp 时候,知道了 Foo<int>的实例化,但是没法同时掌握模版定义和参数实例化,这样也就无法生成具体的类代码。
157+
158+
为了解决这个问题,通常我们会把模板的声明和定义放在一个头文件中(建议这样做),不过也可以分别放在头文件和源文件中,下面就是一个示例:
159+
160+
* [foo.h](../Coding/C++_Template_foo.h):函数模版声明,模版类的定义;
161+
* [foo.cpp](../Coding/C++_Template_foo.cpp):函数模版定义,模板成员函数的定义;
162+
* [main.cpp](../Coding/C++_Template_main.cpp):使用函数模版和模版类。
163+
164+
这里在模版类的实现文件中放置具体的`模版实例化`,就可以生成具体的实例化对象了。
96165

97166
# 隐式接口和编译期多态
98167

@@ -221,7 +290,10 @@ void f(){} // 注意:这里没有"模板实参"
221290
《Effective C++ 模板与泛型编程》
222291
《Effective C++ 条款 25》
223292
[Cpp Reference-Templates](http://en.cppreference.com/w/cpp/language/templates)
293+
[Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file)
294+
[Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file? ](https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl)
224295
[类模板定义及实例化](http://www.cnblogs.com/assemble8086/archive/2011/10/02/2198308.html)
225296
[C++ typename的起源与用法](http://feihu.me/blog/2014/the-origin-and-usage-of-typename/)
226297
[C++模板的偏特化与全特化](http://harttle.com/2015/10/03/cpp-template.html)
298+
[C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?](https://www.zhihu.com/question/20630104)
227299

Coding/C++_Class_Func.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* @Author: [email protected]
3+
* @Last Modified time: 2016-09-06 08:50:34
4+
*/
5+
6+
#include <iostream>
7+
using namespace std;
8+
9+
class A{
10+
public:
11+
A(int x): data(x){}
12+
void print_data() const{
13+
cout << "Data: " << data << endl;
14+
// set_data(1); Error
15+
// member function 'set_data' not viable: 'this' argument has type 'const A', but function is not marked const
16+
}
17+
void set_data(int x){
18+
data = x;
19+
print_data(); // no-const function call const function.
20+
}
21+
// Here we define a overload function.
22+
void set_data(int x) const{
23+
size = x; // mutable variable can be modified in const func.
24+
cout << "Size: " << size << endl;
25+
}
26+
27+
void update(int x){
28+
data = x;
29+
cout << "Data: " << data << endl;
30+
}
31+
32+
private:
33+
int data = 0;
34+
mutable int size = 0; // Can be modified in const function.
35+
36+
};
37+
38+
int main() {
39+
A a(2);
40+
a.set_data(10);
41+
a.print_data(); // No-const object call const function.
42+
const A b(-2);
43+
b.set_data(20); // Here const object call const function.
44+
// member function 'update' not viable: 'this' argument has type 'const A', but function is not marked const
45+
// b.update(10); Error.
46+
}
47+

Coding/C++_Template_foo.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* @Author: [email protected]
3+
* @Last Modified time: 2016-09-06 11:32:32
4+
*/
5+
6+
#include <iostream>
7+
#include "C++_Template_foo.h"
8+
template<typename T>
9+
void foo()
10+
{
11+
std::cout << "Here I am!\n";
12+
}
13+
14+
template<typename T>
15+
void Foo<T>::g()
16+
{
17+
std::cout << "Foo<T>::g()" << std::endl;
18+
}
19+
20+
// Important here, define the template function and class.
21+
template void foo<int>();
22+
template class Foo<int>;

Coding/C++_Template_foo.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <iostream>
2+
// Function template.
3+
template<typename T>
4+
void foo();
5+
6+
// Class template.
7+
template<typename T>
8+
class Foo {
9+
public:
10+
void f();
11+
void g();
12+
};
13+
template<typename T>
14+
inline
15+
void Foo<T>::f()
16+
{
17+
std::cout << "Inline function f()" << std::endl;
18+
}

Coding/C++_Template_main.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* @Author: [email protected]
3+
* @Last Modified time: 2016-09-06 11:32:51
4+
*/
5+
6+
#include "C++_Template_foo.h"
7+
int main()
8+
{
9+
foo<int>();
10+
11+
Foo<int> x;
12+
x.f();
13+
x.g();
14+
}

DataBase/Engine.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ MyISAM引擎使用B+Tree作为索引结构,**叶节点的data域存放的是
1212

1313
![][1]
1414

15-
这里设表一共有三列,假设我们以Col1为主键,则上图是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址,这种索引方式叫做`非聚集索引`。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:
15+
这里设表一共有三列,假设我们以Col1为主键,则上图是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址,这种索引方式叫做**非聚集索引**。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:
1616

1717
![][2]
1818

0 commit comments

Comments
 (0)