双重派发 双重委派 双派发 double dispatch

参考自《c++高级编程》

解决的问题:

在多态时,初始化需要明确接口的实际类型:

Animal animal= bear();

animal.move();

这个animal指针指向真正的实例化类,调用的是animal接口里的方法。编译时可以通过

这个是运行时多态!!!

如果确定类型时需要两个,甚至多个类型确认,就会有问题。

比如 animal.eats( Animal a)。

编译器只能重载!!!参数是个基类Animal 类型。而我们在实现中没有这个方法,无法找到成员函数实现:bool eats( Animal a);

 这是没有意义的。熊吃动物吗?只有知道具体的才行,而编译器看到 Animal参数只会去找对应的函数实现。

熊的实现一般如下:

class Bear : Animal{

  bool eats( Cat cat);

   bool eats( Dog cat);

bool eats( Animal a);//这个没有

};

可以看到没有 eats(Animal a)这个成员函数。因此会导致编译错误。

a是个基类类型,编译器无法判定这个函数重载的是哪个:是dog,还是Cat。

多态只有在运行时才能体现出来。

 

第一种方法解决:

既然编译器找不到 eats(Animal a) 的实现。在Animal接口中添加实现。

class Animal: Animal{

  bool eats( Animal a){

 }

}

这样就可以通过编译了。

这时用 a.eatenBy(*this),a是运行行多态,可以确定类型。*this也是具体实现,可以得到类型。即双分派。 animal.eats这个是第一个动态;a.eatenBy是第二次。

第二种,采用奇异模板 CRTP

将子类作为模板参数传给基类,让基类把参数强制cast。

第三种,c++23

借助Deducing this,可以简化CRTP
1//// Before
2// CRTP
3template <class Derived>
4struct Base {
5    void foo() {
6        auto& self = *static_cast<Derived*>(this);
7        self.bar();
8    }
9};
10
11struct Derived : Base<Derived> {
12    void bar() const {
13        std::cout << "CRTP Derived\n";
14    }
15};
16
17////////////////////////////////////////////
18//// After
19// Deducing this
20struct Base {
21    template <class Self>
22    void foo(this Self& self) {
23        self.bar();
24    }
25};
26
27struct Derived : Base {
28    void bar() const {
29        std::cout << "Deducing this Derived\n";
30    }
31};
这种新的方式实现CRTP,可以省去CR,甚至是T,要更加自然,更加清晰。
posted @   Bigben  阅读(169)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2018-12-17 Python之——CentOS 6.5安装Python2.7.14
点击右上角即可分享
微信分享提示