鸭子类型

" When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck. - James Whitcomb Riley, 1849-1916"

鸭子类型的说法本来是从 python 这种支持动态编译的语言中来的

class Duck:
    def shout(self):
        print("Duck shout")
    def fly(self):
        print("Duck fly")

class Goose:
    def shout(self):
        print("Goose shout")
    def fly(self):
        print("Goose fly")

class Dog: 
    def walk(self):
        print("Dog walk")
    def wolf(self):
        print("Dog wolf")

def test (bird):
    bird.shout()
    bird.fly()

test(Duck())  # OK: output -> "Duck shout\nDuck fly\n"
test(Goose()) # OK: output -> "Goose shout\nGoose fly\n"
test(Dog())   # ERROR
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

这里传进去的鸟可以叫和飞,如果我们说它是鸭子那它就是鸭子的行为,如果说是鹅那这就是鹅的行为,但狗不会这两个动作,所以说它是狗这是不对的
这也体现了一种多态性

而我们可以利用前面 模板SFINAE 来模拟出这种功能

test 函数添加两个判断检测参数 bird 是否含有 fly()shout() 两种动作

template<typename T>
void test (T&& bird,
           decltype(bird.fly())* func1 = nullptr,
           decltype(bird.shout())* func2 = nullptr) {
    bird.fly();
    bird.shout();
}
1
2
3
4
5
6
7

都有的话满足要求可以执行函数体内容

class Duck {
public:
    void fly () {
        std::cout << "Duck fly\n";
    }
    void shout () {
        std::cout << "Duck shout\n";
    }
};
class Goose {
public:
    void fly () {
        std::cout << "Goose fly\n";
    }
    void shout () {
        std::cout << "Goose shout\n";
    }
};
class Dog {
public:
    void walk () {
        std::cout << "Dog walk\n";
    }
    void wolf () {
        std::cout << "Dog wolf\n";
    }
};
int main () {
    test(Duck()); // OK: 输出和上面一样
    test(Goose()); // OK: 输出和上面一样
    test(Dog()); // ERROR
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

解释在上面对 .py 代码的解释中也可体现

Last Updated: 3/20/2023, 10:02:16 PM