@@ -67,3 +67,96 @@ template <typename T>
6767using Coord = Pair<T>; // Coord is an alias for Pair<T>
6868```
6969
70+ ## 类
71+
72+ 类的成员变量,成员函数是隐式内联的,所以放在头文件中被多个源文件引用的时候,不违反ODR原则。
73+
74+ 在类中,不强制声明语句位于使用之前,只要他们都在同一个类中即可。
75+
76+ 调用常量类对象内部的函数,要将此成员函数声明为` const ` 。
77+
78+ ``` cpp
79+ void foo () const {
80+ //...
81+ }
82+ ```
83+
84+ ` struct ` 和` class ` 仅有的差异:` struct ` 默认使用` public: ` ,而` class ` 默认使用` private: ` 。在继承性上也是这样。
85+
86+ ` protect: ` 允许派生的类访问,其可见性介于两者之间。
87+
88+
89+ ### 推荐实践
90+
91+ 1 . 不要让成员函数返回引用,否则将会使得成员变量被以外修改。
92+ 2 . 不推荐使用成员函数,为了使类的实现更加简洁。
93+
94+ ### 成员初始化列表
95+
96+ 现代C++使用成员初始化列表,而不是直接初始化列表。具体是:
97+
98+ ``` cpp
99+ class Foo {
100+ int m_a{};
101+ int m_b{};
102+
103+ Foo (int a, int b) : m_a{a}, m_b{b} {
104+ //other...
105+ }
106+ }
107+ ```
108+
109+ 以前(C++03)之前则是用的`()`直接初始化。
110+
111+ 成员初始化的顺序和成员初始化列表无关,只跟泪中定义成员变量的顺序有关。
112+
113+ ### `std::string_view`特殊处理
114+
115+ 一个例子:
116+
117+ ```cpp
118+ #include <iostream>
119+ #include <string>
120+ #include <string_view>
121+
122+ class Ball
123+ {
124+ private:
125+ std::string m_color { "none" };
126+ double m_radius { 0.0 };
127+
128+ public:
129+ Ball(std::string_view color, double radius)
130+ : m_color { color }
131+ , m_radius { radius }
132+ {
133+ }
134+
135+ const std::string& getColor() const { return m_color; }
136+ double getRadius() const { return m_radius; }
137+ };
138+
139+ void print(const Ball& ball)
140+ {
141+ std::cout << "Ball(" << ball.getColor() << ", " << ball.getRadius() << ")\n";
142+ }
143+
144+ int main()
145+ {
146+ Ball blue { "blue", 10.0 };
147+ print(blue);
148+
149+ Ball red { "red", 12.0 };
150+ print(red);
151+
152+ return 0;
153+ }
154+ ```
155+
156+ > 为什么这里构造函数需要用` string_view ` 作为参数?不能用` const string& ` 来替换?
157+
158+ ` string_view ` 提供了灵活性,如果选择后者,那么如果传入一个C语言的字面量字符串的时候,就必须在堆上构建临时的` string ` 对象,而这对性能开销很大;对于前者,永远不会构造临时对象,而是只有一个指针,在真正初始化的时候完成一次复制。(甚至后面还能用移动语义)
159+
160+ > 为什么` getter ` 不能像上面一样反过来?
161+
162+ 因为在类内部的存储对象就是真正的` string ` ,给出它的引用使得外部访问的类型明确,不会造成歧义;同时也提示这个引用的生命周期是明确的————跟成员变量一致。
0 commit comments