Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何避免生产中的vtable查找,并且仍然能够在单元测试中广泛模拟?_C++_Performance_Unit Testing_Mocking_Vtable - Fatal编程技术网

C++ 如何避免生产中的vtable查找,并且仍然能够在单元测试中广泛模拟?

C++ 如何避免生产中的vtable查找,并且仍然能够在单元测试中广泛模拟?,c++,performance,unit-testing,mocking,vtable,C++,Performance,Unit Testing,Mocking,Vtable,在像C#这样的语言中,我经常让我的类依赖于接口而不是具体的类,即使只有一个“真正的”实现。这是为了使单元测试更容易(通过创建模拟) 在C++编程时,我希望最大性能,并且仍然使用TDD和嘲弄。有没有一种方法可以同时实现这两个目标?也就是说,能够在测试时进行模拟,并且在生产代码中仍然有直接的具体调用 如何在C++中实现?< P>,而不是接口和运行时多态: struct IService { virtual ~IService() = 0; virtual void foo() = 0

在像C#这样的语言中,我经常让我的类依赖于接口而不是具体的类,即使只有一个“真正的”实现。这是为了使单元测试更容易(通过创建模拟)

在C++编程时,我希望最大性能,并且仍然使用TDD和嘲弄。有没有一种方法可以同时实现这两个目标?也就是说,能够在测试时进行模拟,并且在生产代码中仍然有直接的具体调用


如何在C++中实现?

< P>,而不是接口和运行时多态:

struct IService
{
    virtual ~IService() = 0;
    virtual void foo() = 0;
    // ...
};

class C
{
public:
    explicit C(IService& service) : service(service) {}

    void DoJob() { /*..*/ service.foo(); /*..*/ }
    // ..
private:
     IService& service;
};
生产中:

struct Service : IService
{
    void foo() override;
    // ...
};

Service service;
C c(service);
c.doJob();
struct Service
{
    void foo();
    // ...
};

Service service;
C c(service); // or before C++17 C<Service> c(service);
c.doJob();
试验中

struct ServiceMock : IService
{
    void foo() override;
    // ...
};

ServiceMock service;
C c(service);
c.doJob();
您可以为此使用模板:

// No interface to provide requirement, so document it
// TService must have `foo()`, ...
// or wait for C++20 concept
template <typename TService>
class C
{
public:
    explicit C(TService& service) : service(service) {}

    void DoJob() { /*..*/ service.foo(); /*..*/ }
    // ..
private:
     TService& service;
};

C++不仅提供动态多态性,而且提供了动态的多态性。E使用vtable查找进行后期绑定,但也使用模板进行静态多态性。这当然会导致更长的编译时间,因为模板实现需要驻留在头文件中,当其他每次函数调用都涉及到跳来跳去,弄清楚真正使用的是哪个组件时,很难理解代码实际上在做什么。模板可以解决虚拟调用问题,但它们不会使代码变得更好。这也意味着您正在测试的代码与您的生产代码有一点点距离。当编译器看到虚拟类只有一个实现时,可能会优化vtable查找?或者,在为生产构建时,可以使用某种技巧将抽象类的指针与具体类的指针交换?宏?看看这个。对于gcc 9.2和-O2,多态调用和正常函数调用之间没有区别。只有多态类的构造需要一条CPU指令。@Ptaq666:这是因为GCC足够聪明,不会在您的示例中使用多态调用。它计算出编译时已经存在的运行时类型。这是可能的,因为不依赖于任何外部因素。因此,如果我理解正确,当依赖项通过引用传递时,没有动态调用(vtable lookup)?即使该引用是对抽象类型(如IService)的引用,您也可以使用
IService
(使用引用或指针)进行动态分派,但不使用模板版本。
struct ServiceMock
{
    void foo();
    // ...
};

ServiceMock service;
C c(service); // or before C++17 C<ServiceMock> c(service);
c.doJob();
OuterService<ServiceA<Service1, Service2>, ServiceB<Service1, Service2>> outer(serviceA, servceB);
// versus
// OuterService outer(serviceA, servceB);