gpt4 book ai didi

c++ - 现代编译器可以在使用依赖注入(inject)时去虚拟化函数调用吗

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:14:06 24 4
gpt4 key购买 nike

当您希望您的代码可测试时,依赖注入(inject)是一种非常重要的模式,它一直在大型 C++ 项目中使用。

这是一个简单的例子:

// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0

class FooInterface {
public:
virtual void f() = 0;
virtual ~FooInterface() = default;
};

class Foo : public FooInterface {
public:
void f() override { /* Actual work */ }
};

class MockFoo : public FooInterface {
public:
void f() override { /* Mock code */ }
};

class Bar {
public:
Bar(std::unique_ptr<FooInterface>&& foo) : foo_(std::move(foo)) { }
void b() { foo_->f(); }

private:
std::unique_ptr<FooInterface> foo_;
};

// In production
void production() {
auto bar = std::make_unique<Bar>(std::make_unique<Foo>());
bar->b();
// ...
}

// In tests
void test() {
auto bar = std::make_unique<Bar>(std::make_unique<MockFoo>());
bar->b();
// ...
}

我一直有一个疑问是编译器是否能够将这种虚函数的使用去虚拟化。

我知道在一般情况下不可能知道正在使用哪个派生类,但在上面的示例中,编译器知道在 productiontest 中正在使用哪些对象 函数,因为它们被显式实例化。

现代编译器是否可以优化这种特殊情况并删除虚函数调用,因为它们知道在编译时正在实例化哪个派生类?

如果无法对这个特定示例进行去虚拟化,是否可以对其进行任何更改以使调用被去虚拟化?

最佳答案

这取决于编译器和您正在处理的特定代码。根据我的经验,如果您真的想避免 virtual 调用,则不应依赖它。

例如,如果 f()noexcept,Clang/LLVM -O2 下将您的示例去虚拟化:

class FooInterface {
public:
virtual void f() noexcept = 0;
virtual ~FooInterface() = default;
};

但其他主要编译器不会。您的里程可能会有所不同。

关于c++ - 现代编译器可以在使用依赖注入(inject)时去虚拟化函数调用吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57538208/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com