docs: address community issue feedback (#5 #338 #142 #246 #136 #303)

- const README: rewrite the space-saving claim per issue #5 follow-ups
  (constant-expression const vs #define immediates; which const qualify
  as constant expressions)
- const README: fix the class-section diagnosis per issue #338 (overload
  resolution picks the const overload; the restriction only surfaces
  once that overload is removed)
- sizeof README: virtual-inheritance result is compiler-dependent
  (GCC merges vbptr+vfptr -> 16, MSVC keeps them separate -> 32) #246
- static README: new section on internal linkage / access restriction
  with anonymous-namespace comparison #142
- 10-day practice: full problem list table + fixed day links #136
- new design_pattern/singleton/singleton_default.hpp: reusable
  thread-safe CRTP singleton template, compile+concurrency tested #303
This commit is contained in:
light-city
2026-10-13 19:23:54 +08:00
parent cfc9af1fcb
commit dfe1c933b3
159 changed files with 20461 additions and 182 deletions

View File

@@ -1,10 +1,12 @@
# 纯虚函数和抽象类
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/abstract/) 同步生成,网站版本含多语言与更新排版。
# C++ 纯虚函数与抽象类
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.纯虚函数与抽象类
@@ -23,7 +25,7 @@ public:
抽象类只能作为基类来派生新类使用,不能创建抽象类的对象,抽象类的指针和引用->由抽象类派生出来的类的对象!
> 代码样例:[abstract_base.h](./abstract_base.h)、[pure_virtual.cpp](./pure_virtual.cpp)
> 代码样例:[abstract_base.h](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/abstract_base.h)、[pure_virtual.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/pure_virtual.cpp)
## 2.实现抽象类
@@ -45,11 +47,11 @@ public:
};
```
> 代码样例:[abstract.cpp](./abstract.cpp)
> 代码样例:[abstract.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/abstract.cpp)
## 3.重要点
- [纯虚函数使一个类变成抽象类](./interesting_facts1.cpp)
- [纯虚函数使一个类变成抽象类](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/interesting_facts1.cpp)
```cpp
// 抽象类至少包含一个纯虚函数
class Base{
@@ -62,7 +64,7 @@ private:
};
```
- [抽象类类型的指针和引用](./interesting_facts2.cpp)
- [抽象类类型的指针和引用](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/interesting_facts2.cpp)
```cpp
class Derived : public Base {
public:
@@ -81,7 +83,7 @@ int main(void)
}
```
- [如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类](./interesting_facts3.cpp)
- [如果我们不在派生类中覆盖纯虚函数,那么派生类也会变成抽象类](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/interesting_facts3.cpp)
```cpp
// Derived为抽象类
class Derived: public Base
@@ -91,7 +93,7 @@ public:
};
```
- [抽象类可以有构造函数](./interesting_facts4.cpp)
- [抽象类可以有构造函数](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/interesting_facts4.cpp)
```cpp
// 抽象类
class Base {
@@ -111,7 +113,7 @@ public:
};
```
- [构造函数不能是虚函数,而析构函数可以是虚析构函数](./interesting_facts5.cpp)
- [构造函数不能是虚函数,而析构函数可以是虚析构函数](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/interesting_facts5.cpp)
```cpp
// 抽象类
class Base {
@@ -137,4 +139,4 @@ public:
抽象类由派生类继承实现!
> 代码样例:[derived_full.cpp](./derived_full.cpp)
> 代码样例:[derived_full.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/abstract/derived_full.cpp)

View File

@@ -1,10 +1,12 @@
# assert那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/assert/) 同步生成,网站版本含多语言与更新排版。
# C++ assert 断言
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
@@ -20,7 +22,7 @@ assert 宏的原型定义在 <assert.h>(C)、<cassert>(C++)中。其作
void assert(int expression);
```
> 代码样例:[assert.c](./assert.c)
> 代码样例:[assert.c](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/assert/assert.c)
```c
#include <stdio.h>
#include <assert.h>
@@ -58,4 +60,4 @@ assert: assert.c:13: main: Assertion 'x==7' failed.
#define NDEBUG // 加上这行,则 assert 不可用
```
> 样例代码:[ignore_assert.c](./ignore_assert.c)
> 样例代码:[ignore_assert.c](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/assert/ignore_assert.c)

View File

@@ -1,8 +1,12 @@
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/bit/) 同步生成,网站版本含多语言与更新排版。
# C++ 位域
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## Bit field 是什么?
@@ -108,7 +112,7 @@ struct stuff
这里 stuff.field1 与 stuff.field2 之间有一个 2 Bits 的空隙,stuff.field3 则存储在下一个 unsigned int 中,该结构现在大小为 3 * 32 = 96 Bits。
学习代码见:[bit.cpp](bit.cpp)
学习代码见:[bit.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/bit/bit.cpp)
## 位域的初始化和位的重映射

View File

@@ -1,10 +1,12 @@
# C实现C++的面向对象特性
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/c-polymorphism/) 同步生成,网站版本含多语言与更新排版。
# C 语言实现 C++ 多态
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.C++实现案例
@@ -12,7 +14,7 @@ C++中的多态:在C++中会维护一张虚函数表,根据赋值兼容规则
如果一个父类的指针或者引用调用父类的虚函数则该父类的指针会在自己的虚函数表中查找自己的函数地址,如果该父类对象的指针或者引用指向的是子类的对象,而且该子类已经重写了父类的虚函数,则该指针会调用子类的已经重写的虚函数。
学习案例代码见:[c++_examp.cpp](./c++_examp.cpp)
学习案例代码见:[c++_examp.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/c_poly/c++_examp.cpp)
@@ -38,4 +40,4 @@ C语言中是没有class类这个概念的,但是有struct结构体,我们
学习案例代码见:[c_examp.c](./c_examp.c)
学习案例代码见:[c_examp.c](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/c_poly/c_examp.c)

View File

@@ -1,8 +1,12 @@
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/const/) 同步生成,网站版本含多语言与更新排版。
# C++ const 常量与修饰
## 关于作者
微信公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.const含义
@@ -34,8 +38,9 @@ void f(const int i){
+ 可以节省空间,避免不必要的内存分配
+ const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像`#define`一样给出的是立即数。
+ const定义的常量在程序运行过程中只有一份拷贝,而`#define`定义的常量在内存中有若干个拷贝。
+ 以整型/枚举类型、常量表达式初始化的 const(即常量表达式)在用法上更接近编译期常量:不取地址、仅使用其值时通常被优化成立即数,与 `#define` 类似;取地址或跨编译单元 odr-use 时才会落到内存,且全程序只有一份。
+ `#define` 展开为字面量后以立即数形式编入指令,指令本身也占内存,多处使用即多处出现(见 [issue #5](https://github.com/Light-City/CPlusPlusThings/issues/5) 的讨论)。
+ 注意:并非所有 const 变量都是常量表达式——只有整数/枚举类型且以常量表达式初始化的才是;其他 const 变量只是 const 限度的变量(如浮点、自定义类型,标准并未规定其可用常量表达式初始化,`constexpr` 才是编译期常量的正确表达)。
## 3.const对象默认为文件局部变量
@@ -358,7 +363,7 @@ int main()
```
> 编译:bazel run basic_content/const/class_const/first_example:main<br>
此时报错,上面getCount()方法中调用了一个add方法,而add方法并非const修饰,所以运行报错。也就是说const成员函数只能访问const成员函数。
此时报错:getCount() 是 const 成员函数,其中的 add() 重载决议只会匹配 const 版本(`int add(int num) const`);把这个 const 版本注释掉后,才会因调用了非 const 的 add() 而报错。即:const 对象只能访问 const 成员函数,非 const 对象可以访问任意成员函数(见 [issue #338](https://github.com/Light-City/CPlusPlusThings/issues/338))。
当调用改为:
@@ -410,4 +415,4 @@ static int ap;
int Apple::ap=666
```
对于此项,c++11不能进行声明并初始化,也就是上述使用方法。
对于此项,c++11不能进行声明并初始化,也就是上述使用方法。

View File

@@ -1,10 +1,12 @@
# decltype那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/decltype/) 同步生成,网站版本含多语言与更新排版。
# C++ decltype 类型推导
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.基本使用
decltype的语法是:
@@ -69,7 +71,7 @@ auto multiply(T x, T y)->decltype(x*y)
}
```
完整代码见:[decltype.cpp](decltype.cpp)
完整代码见:[decltype.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/decltype/decltype.cpp)
## 2.判别规则
@@ -135,4 +137,4 @@ decltype(Func(1)) var13=true;//const bool
decltype(i++) var14 = i;//int i++返回右值
```
学习参考:https://www.cnblogs.com/QG-whz/p/4952980.html
学习参考:https://www.cnblogs.com/QG-whz/p/4952980.html

View File

@@ -1,10 +1,12 @@
# 从初级到高级的enum那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/enum/) 同步生成,网站版本含多语言与更新排版。
# C++ enum 枚举类型
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 传统行为
@@ -37,7 +39,7 @@ int main()
- 会隐式转换为int
- 用来表征枚举变量的实际类型不能明确指定,从而无法支持枚举类型的前向声明。
具体实现见:[tradition_color.cpp](tradition_color.cpp)
具体实现见:[tradition_color.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/enum/tradition_color.cpp)
## 经典做法
@@ -72,7 +74,7 @@ struct Color1
};
```
具体实现见:[classic_practice.cpp](classic_practice.cpp)
具体实现见:[classic_practice.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/enum/classic_practice.cpp)
## C++11 的枚举类
@@ -110,7 +112,7 @@ enum class Color3:char
char c3 = static_cast<char>(Color3::RED);
```
具体实现见:[classic_practice.cpp](classic_practice.cpp)
具体实现见:[classic_practice.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/enum/classic_practice.cpp)
## 类中的枚举类型
@@ -161,4 +163,4 @@ public:
枚举常量不会占用对象的存储空间,它们在编译时被全部求值。
枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点。
枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点。

View File

@@ -1,16 +1,18 @@
# explicit(显式)关键字那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/explicit/) 同步生成,网站版本含多语言与更新排版。
# C++ explicit 显式转换
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
- explicit 修饰构造函数时,可以防止隐式转换和复制初始化
- explicit 修饰转换函数时,可以防止隐式转换,但按语境转换除外
代码参见:[.explicit.cpp](./explicit.cpp)
代码参见:[.explicit.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/explicit/explicit.cpp)
参考链接:
> https://stackoverflow.com/questions/4600295/what-is-the-meaning-of-operator-bool-const
> https://stackoverflow.com/questions/4600295/what-is-the-meaning-of-operator-bool-const

View File

@@ -1,10 +1,12 @@
# extern "C"
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/extern/) 同步生成,网站版本含多语言与更新排版。
# C++ extern 链接说明
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.C++与C编译区别
@@ -118,11 +120,11 @@ int add(int x,int y);
上述案例源代码见:
- [add.h](extern_c++/add.h)
- [add.h](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/extern/extern_c++/add.h)
- [add.c](extern_c++/add.c)
- [add.c](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/extern/extern_c++/add.c)
- [add.cpp](extern_c++/add.cpp)
- [add.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/extern/extern_c++/add.cpp)
## 2.C中调用C++函数
@@ -166,11 +168,11 @@ gcc add.c add.o -o main
上述案例源代码见:
- [add.h](extern_c/add.h)
- [add.h](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/extern/extern_c/add.h)
- [add.c](extern_c/add.c)
- [add.c](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/extern/extern_c/add.c)
- [add.cpp](extern_c/add.cpp)
- [add.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/extern/extern_c/add.cpp)
综上,总结出使用方法,在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。所以使用extern "C"全部都放在于cpp程序相关文件或其头文件中。
@@ -209,4 +211,4 @@ extern int add();
```
不过与C++调用C接口不同,C++确实是能够调用编译好的C函数,而这里C调用C++,不过是把C++代码当成C代码编译后调用而已。也就是说,C并不能直接调用C++库函数。
不过与C++调用C接口不同,C++确实是能够调用编译好的C函数,而这里C调用C++,不过是把C++代码当成C代码编译后调用而已。也就是说,C并不能直接调用C++库函数。

View File

@@ -1,10 +1,12 @@
# 友元函数与友元类
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/friend/) 同步生成,网站版本含多语言与更新排版。
# C++ friend 友元
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 0.概述
@@ -35,7 +37,7 @@ friend <类型><友元函数名>(<参数表>);
注意,友元函数只是一个普通函数,并不是该类的类成员函数,它可以在任何地方调用,友元函数中通过对象名来访问该类的私有或保护成员。
具体代码见:[friend_func.cpp](friend_func.cpp)
具体代码见:[friend_func.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/friend/friend_func.cpp)
```c++
#include <iostream>
@@ -74,7 +76,7 @@ friend class <友元类名>;
类B是类A的友元,那么类B可以直接访问A的私有成员。
具体代码见:[friend_class.cpp](friend_class.cpp)
具体代码见:[friend_class.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/friend/friend_class.cpp)
```c++
#include <iostream>
@@ -112,4 +114,4 @@ int main()
假如类B是类A的友元,类C继承于类A,那么友元类B是没办法直接访问类C的私有或保护成员。
- 友元关系没有传递性
假如类B是类A的友元,类C是类B的友元,那么友元类C是没办法直接访问类A的私有或保护成员,也就是不存在“友元的友元”这种关系。
假如类B是类A的友元,类C是类B的友元,那么友元类C是没办法直接访问类A的私有或保护成员,也就是不存在“友元的友元”这种关系。

View File

@@ -1,10 +1,12 @@
# inline那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/inline/) 同步生成,网站版本含多语言与更新排版。
# C++ inline 内联函数
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.类中内联
@@ -131,7 +133,4 @@ int main()
return 0;
}
```
```

View File

@@ -1,10 +1,12 @@
# 宏那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/macro/) 同步生成,网站版本含多语言与更新排版。
# C++ 宏与条件编译
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.宏中包含特殊符号
@@ -113,7 +115,7 @@ int main() {
}
```
上述代码见:[sig_examp.cpp](sig_examp.cpp)
上述代码见:[sig_examp.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/macro/sig_examp.cpp)
## 2.do{...}while(0)的使用
@@ -226,7 +228,6 @@ int fc()
}
```
上述代码见:[do_while.cpp](do_while.cpp)
学习文章:<https://www.cnblogs.com/lizhenghn/p/3674430.html>
上述代码见:[do_while.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/macro/do_while.cpp)
学习文章:<https://www.cnblogs.com/lizhenghn/p/3674430.html>

View File

@@ -1,14 +1,15 @@
# :: 范围解析运算符那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/namespace/) 同步生成,网站版本含多语言与更新排版。
# C++ 命名空间
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
- 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间
- 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的
- 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的
具体代码见:[maohao.cpp](maohao.cpp)
具体代码见:[maohao.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/maohao/maohao.cpp)

View File

@@ -1,10 +1,12 @@
# 引用与指针那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/pointer-vs-reference/) 同步生成,网站版本含多语言与更新排版。
# C++ 指针与引用
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.引用与指针
@@ -171,4 +173,4 @@ End of assembler dump.
C++中引入了引用操作,在对引用的使用加了更多限制条件的情况下,保证了引用使用的安全性和便捷性,还可以保持代码的优雅性。在适合的情况使用适合的操作,引用的使用可以一定程度避免“指针满天飞”的情况,对于提升程序稳定性也有一定的积极意义。最后,指针与引用底层实现都是一样的,不用担心两者的性能差距。
上述部分参考自:<http://irootlee.com/juicer_pointer_reference/#>
上述部分参考自:<http://irootlee.com/juicer_pointer_reference/#>

View File

@@ -1,4 +1,6 @@
# 类大小计算
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/sizeof/) 同步生成,网站版本含多语言与更新排版。
# C++ sizeof 运算符
首先来个总结,然后下面给出实际例子,实战!
@@ -194,11 +196,10 @@ class C : virtual public A, virtual public B
int main()
{
/**
* @brief 8 8 16 派生类虚继承多个虚函数,会继承所有虚函数的vptr
* @brief GCC: 8 8 16(虚基类指针与虚函数表指针合并);MSVC/Windows: 8 8 32(虚基类指针与虚函数表指针分别存储),结果与编译器相关,见 issue #246
*/
cout<<sizeof(A)<<" "<<sizeof(B)<<" "<<sizeof(C);
return 0;
}
```
```

View File

@@ -1,10 +1,12 @@
# static那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/static/) 同步生成,网站版本含多语言与更新排版。
# C++ static 静态成员与生存期
## 关于作者
微信公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
当与不同类型一起使用时,Static关键字具有不同的含义。我们可以使用static关键字:
@@ -277,3 +279,21 @@ int main()
return 0;
}
```
### 6.static 的内部链接(限定访问范围)
感谢 [issue #142](https://github.com/Light-City/CPlusPlusThings/issues/142) 指出:static 修饰全局变量/函数时,还起到**限定访问范围**的作用——将其链接性从外部链接(external linkage)改为内部链接(internal linkage),效果类似匿名命名空间:
- 非 static 的全局变量:其他编译单元可以通过 `extern` 声明访问;
- static 全局变量/函数:仅当前编译单元可见,`extern` 声明也无法链接到(上面的 undefined reference 正是这个原因)。
现代 C++ 中更推荐用**匿名命名空间**表达"仅本文件可见"(对类型同样有效),但理解 static 的这一层含义在阅读旧代码时非常重要。
```cpp
// file1.cpp
static int hidden = 42; // 内部链接:其他文件 extern 不可见
int visible = 1; // 外部链接:其他文件可 extern 访问
namespace { // 匿名命名空间:等价且更现代的写法
int also_hidden = 7;
}
```

View File

@@ -1,10 +1,12 @@
# 一文搞懂C和C++中struct
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/struct/) 同步生成,网站版本含多语言与更新排版。
# C++ struct 结构体
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.C中struct
@@ -52,7 +54,7 @@ int main() {
I am Base func
```
完整代码见:[struct_func.c](./struct_func.c)
完整代码见:[struct_func.c](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/struct/struct_func.c)
## 2.C++中struct
@@ -135,7 +137,7 @@ int main() {
}
```
完整代码见:[struct_func.cpp](struct_func.cpp)
完整代码见:[struct_func.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/struct/struct_func.cpp)
> 继承案例
@@ -167,7 +169,7 @@ int main() {
}
```
完整代码见:[ext_struct_func.cpp](./ext_struct_func.cpp)
完整代码见:[ext_struct_func.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/struct/ext_struct_func.cpp)
> 同名函数
@@ -212,7 +214,7 @@ int main() {
return 0;
}
```
完整代码见:[struct_func_func.cpp](./struct_func_func.cpp)
完整代码见:[struct_func_func.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/struct/struct_func_func.cpp)
## 3.总结
@@ -224,4 +226,4 @@ int main() {
| 在C结构体声明中不能使用C++访问修饰符。 | public、protected、private 在C++中可以使用。 |
| 在C中定义结构体变量,如果使用了下面定义必须加struct。 | 可以不加struct |
| 结构体不能继承(没有这一概念)。 | 可以继承 |
| 若结构体的名字与函数名相同,可以正常运行且正常的调用! | 若结构体的名字与函数名相同,使用结构体,只能使用带struct定义! |
| 若结构体的名字与函数名相同,可以正常运行且正常的调用! | 若结构体的名字与函数名相同,使用结构体,只能使用带struct定义! |

View File

@@ -1,12 +1,14 @@
# struct与class区别
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/struct-vs-class/) 同步生成,网站版本含多语言与更新排版。
# C++ struct 与 class 区别
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
关于C与C++中struct内容:见[struct那些事](../struct)
关于C与C++中struct内容:见[struct那些事](struct.md)
总的来说,struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。
@@ -16,4 +18,4 @@
默认的继承访问权限。struct 是 public 的,class 是 private 的。
struct 作为数据结构的实现体,它默认的数据访问控制是 public 的,而 class 作为对象的实现体,它默认的成员变量访问控制是 private 的。
struct 作为数据结构的实现体,它默认的数据访问控制是 public 的,而 class 作为对象的实现体,它默认的成员变量访问控制是 private 的。

View File

@@ -1,10 +1,12 @@
# this指针那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/this/) 同步生成,网站版本含多语言与更新排版。
# C++ this 指针
## 关于作者
微信公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.this指针
@@ -74,16 +76,16 @@ int main(){
为了验证this指针是哪一个,现在在`add_age`处添加断点,运行后如下:
![thiscontrust](./img/thiscontrust.png)
![thiscontrust](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/basic_content/this/img/thiscontrust.png)
![genthis](./img/genthis.png)
![genthis](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/basic_content/this/img/genthis.png)
会发现编译器自动为我们加上`A* const`,而不是`A const *this`!
紧接着,上述还有个常函数,那么我们在对`get_age`添加断点,如下:
![constthis](./img/constthis.png)
![constthis](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/basic_content/this/img/constthis.png)
会发现编译器把上述的this,变为`const A* const`,这个大家也能想到,因为这个函数是const函数,那么针对const函数,它只能访问const变量与const函数,不能修改其他变量的值,所以需要一个this指向不能修改的变量,那就是`const A*`,又由于本身this是`const`指针,所以就为`const A* const`!
总结:this在成员函数的开始执行前构造,在成员的执行结束后清除。上述的get_age函数会被解析成`get_age(const A * const this)`,`add_age`函数会被解析成`add_age(A* const this,int a)`。在C++中类和结构是只有一个区别的:类的成员默认是private,而结构是public。this是类的指针,如果换成结构,那this就是结构的指针了。
总结:this在成员函数的开始执行前构造,在成员的执行结束后清除。上述的get_age函数会被解析成`get_age(const A * const this)`,`add_age`函数会被解析成`add_age(A* const this,int a)`。在C++中类和结构是只有一个区别的:类的成员默认是private,而结构是public。this是类的指针,如果换成结构,那this就是结构的指针了。

View File

@@ -1,10 +1,12 @@
# UNION那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/union/) 同步生成,网站版本含多语言与更新排版。
# C++ union 联合体
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
联合(union)是一种节省空间的特殊的类,一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点:
@@ -15,4 +17,4 @@
- 不能含有虚函数
- 匿名 union 在定义所在作用域可直接访问 union 成员
- 匿名 union 不能包含 protected 成员或 private 成员
- 全局匿名联合必须是静态(static)的
- 全局匿名联合必须是静态(static)的

View File

@@ -1,9 +1,12 @@
# using那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/using/) 同步生成,网站版本含多语言与更新排版。
# C++ using 声明与别名
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 基本使用
@@ -48,7 +51,7 @@ int main()
return 0;
}
```
完整代码见:[using_global.cpp](using_global.cpp)
完整代码见:[using_global.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/using/using_global.cpp)
## 改变访问性
```
@@ -67,7 +70,7 @@ protected:
```
类Derived私有继承了Base,对于它来说成员变量n和成员函数size都是私有的,如果使用了using语句,可以改变他们的可访问性,如上述例子中,size可以按public的权限访问,n可以按protected的权限访问。
完整代码见:[derived_base.cpp](derived_base.cpp)
完整代码见:[derived_base.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/using/derived_base.cpp)
## 函数重载
在继承过程中,派生类可以覆盖重载函数的0个或多个实例,一旦定义了一个重载版本,那么其他的重载版本都会变为不可见。
@@ -106,7 +109,7 @@ int main()
```
如上代码中,在派生类中使用using声明语句指定一个名字而不指定形参列表,所以一条基类成员函数的using声明语句就可以把该函数的所有重载实例添加到派生类的作用域中。此时,派生类只需要定义其特有的函数就行了,而无需为继承而来的其他函数重新定义。
完整代码见:[using_derived.cpp](using_derived.cpp)
完整代码见:[using_derived.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/using/using_derived.cpp)
## 取代typedef
C中常用typedef A B这样的语法,将B定义为A类型,也就是给A类型一个别名B
@@ -117,4 +120,4 @@ C中常用typedef A B这样的语法,将B定义为A类型,也就是给A类
typedef vector<int> V1;
using V2 = vector<int>;
```
完整代码见:[using_typedef.cpp](using_typedef.cpp)
完整代码见:[using_typedef.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/using/using_typedef.cpp)

View File

@@ -1,24 +1,26 @@
# virtual那些事
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/virtual/) 同步生成,网站版本含多语言与更新排版。
# C++ virtual 虚函数
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.虚函数与运行多态
对应的代码:[emp.cpp](./set1/emp.cpp)
对应的代码:[emp.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set1/emp.cpp)
**虚函数的调用取决于指向或者引用的对象的类型,而不是指针或者引用自身的类型。**
## 2.vptr与vtable
见[vptr_vtable那些事](../vptr_vtable)
见[vptr_vtable那些事](vptr-vtable.md)
## 3.虚函数中默认参数
对应的代码:[default_arg.cpp](./set2/default_arg.cpp)
对应的代码:[default_arg.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set2/default_arg.cpp)
**默认参数是静态绑定的,虚函数是动态绑定的。 默认参数的使用需要看指针或者引用本身的类型,而不是对象的类型**。
@@ -34,7 +36,7 @@ static成员函数不属于任何类对象或类实例,所以即使给此函
虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,静态成员函数没有this指针,所以无法访问vptr。
代码学习:[static_error.cpp ](./set3/static_error.cpp )
代码学习:[static_error.cpp ](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/static_error.cpp)
(2)**构造函数可以为虚函数吗?**
@@ -48,9 +50,9 @@ static成员函数不属于任何类对象或类实例,所以即使给此函
代码学习:
- [copy_consrtuct.cpp](./set3/copy_consrtuct.cpp)
- [copy_consrtuct.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/copy_consrtuct.cpp)
- [vir_con.cpp](./set3/vir_con.cpp)
- [vir_con.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/vir_con.cpp)
(3)**析构函数可以为虚函数吗?**
@@ -58,9 +60,9 @@ static成员函数不属于任何类对象或类实例,所以即使给此函
代码学习:
- [full_virde.cpp](./set3/full_virde.cpp)
- [full_virde.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/full_virde.cpp)
- [vir_de.cpp ](./set3/vir_de.cpp)
- [vir_de.cpp ](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/vir_de.cpp)
(4)**虚函数可以为私有函数吗?**
@@ -69,8 +71,8 @@ static成员函数不属于任何类对象或类实例,所以即使给此函
代码学习:
- [virtual_function.cpp](./set3/virtual_function.cpp)
- [virtual_function1.cpp](./set3/virtual_function1.cpp)
- [virtual_function.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/virtual_function.cpp)
- [virtual_function1.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/virtual_function1.cpp)
(5)**虚函数可以被内联吗?**
@@ -82,9 +84,9 @@ static成员函数不属于任何类对象或类实例,所以即使给此函
代码学习:
- [virtual_inline.cpp](./set3/virtual_inline.cpp)
- [virtual_inline.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/virtual_inline.cpp)
- [inline_virtual.cpp](./set3/inline_virtual.cpp)
- [inline_virtual.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set3/inline_virtual.cpp)
## 5.RTTI与dynamic_cast
@@ -94,9 +96,9 @@ RTTI(Run-Time Type Identification),通过运行时类型信息程序能够
代码学习:
- [rtti.cpp](./set4/rtti.cpp)
- [warn_rtti.cpp](./set4/warn_rtti.cpp)
- [rtti.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set4/rtti.cpp)
- [warn_rtti.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/virtual/set4/warn_rtti.cpp)
## 6.纯虚函数和抽象类
见[纯虚函数和抽象类那些事](../abstract)
见[纯虚函数和抽象类那些事](abstract.md)

View File

@@ -1,8 +1,12 @@
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/volatile/) 同步生成,网站版本含多语言与更新排版。
# C++ volatile 关键字
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
## 1.volatile
@@ -117,6 +121,5 @@ return a * a;
代码学习:
- [noopt_vola.cpp](./noopt_vola.cpp)
- [volatile.cpp](./volatile.cpp)
- [noopt_vola.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/volatile/noopt_vola.cpp)
- [volatile.cpp](https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/volatile/volatile.cpp)

View File

@@ -1,10 +1,12 @@
# 深入浅出C++虚函数的vptr与vtable
> 本文档由 [C++那些事网站](https://light-city.github.io/stories_things/cpp-things/vptr-vtable/) 同步生成,网站版本含多语言与更新排版。
# C++ 虚指针与虚表机制
## 关于作者:
个人公众号:
![](../img/wechat.jpg)
![](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/img/wechat.jpg)
@@ -24,7 +26,7 @@
开始看代码之前,为了方便大家理解,这里给出调用图:
![base](./img/base.jpg)
![base](https://raw.githubusercontent.com/Light-City/CPlusPlusThings/master/basic_content/vptr_vtable/img/base.jpg)
代码全部遵循标准的注释风格,相信大家看了就会明白,不明白的话,可以留言!
@@ -215,5 +217,4 @@ Dump of assembler code for function Derived::fun2():
0x0000000000400efd <+41>: leaveq
0x0000000000400efe <+42>: retq
End of assembler dump.
```
```