下楼做了核酸,人心惶惶的

1.1 重要的概念

1.1.1 Curiously Recurring Template Pattern

下面是C++世界中的一种实质上的模式: 一个派生类将自己作为模板参数传递给基类.

{.line-numbers}
1
2
3
4
struct Foo : SomeBase<Foo>
{
...
}

你可能会奇怪为什么要这么做. 其中的一个原因是需要能够在基类中访问派生类的类型指针.

例如, 假定SomeBase的每个派生类都实现了一对自己的begin()/end()迭代函数. 那么如何迭代访问SomeBase的派生类呢? 直觉是不要这么做, 因为SomeBase自身并不会提供begin()/end()接口. 下面是实现:

1
2
3
4
5
6
7
8
9
10
11
template <typename Derived>
struct SomeBase
{
void foo()
{
for(auto& item: *static_cast<Derived*>(this))
{
...
}
}
};

要看更详细的例子, 看Chapter 9.

1.1.2 Mixin Inheritance

在C++中, 一个类可以从它的模板参数派生:

1
2
3
4
5
template <typename T>
struct Mixin : T
{
...
};

这种做法被称为mixin inheritance, 它允许多级继承类别. 例如, Foo<Bar<Baz>> x;. 详细的例子请见Chpater 9.

1.1.3 Properties

property实际上就是(通常是私有)字段和对应的getter和setter方法.

1
2
3
4
5
6
7
class Person
{
int age;
public:
int get_age() const { return age; }
void set_age(int value) { age = value; }
};

很多语言提供了语言内置的属性支持功能, 如C#, Koltin. 而C++没有这么做, 并且未来也不大可能这么做. 但是很多编译器都会提供非标准的property的支持. 例如, MSVC, Clang, Intel都支持下面的写法:

{.line-numbers}
1
2
3
4
5
6
7
8
class Person
{
int age_;
public:
int get_age() const { return age_; }
void set_age(int value) { age_ = value; }
__declspec(property(get=get_age, put=set_age)) int age;
};

然后可以这样使用:

1
2
Person person;
person.age = 20; // calls p.set_age(20)

1.2 SOLID Design Principles

SOLID是一组设计准则的简写:

  • 单一职责原准则Single Responsibility Principle, SRP)
  • 开放-关闭准则(Open-Close Principle, OCP)
  • Liskov置换准则(Liskov Substitution Principle, LSP)
  • 接口分离准则( Interface Segregation Principle, ISP)
  • 依赖反转准则 ( Dependency Inversion Principle, DIP)

这些准则是由Robert C.Martin在2000年前后提出的–实际上, 这些来自一系列的设计准则, 并且由Robert在博客中提出.

没啥好说的.