【问题标题】:Using abstract class in C++ for dependency injection在 C++ 中使用抽象类进行依赖注入
【发布时间】:2017-07-04 05:19:58
【问题描述】:

参考this Stackoverflow 问题,我无法弄清楚使用 c++ 风格的接口(即抽象类)实现 DI 的相同问题。我没有增加旧线程,而是创建了这个线程。编译器在最后一行抛出错误。

class IService {
    virtual void DoWork() = 0;
    virtual bool IsRunning() = 0;
};

class ClientA : IService {
    void DoWork() {
        std::cout << "Work in progress inside A";
    }
    bool IsRunning() { 
        return true; 
    }
};

class ClientB : IService {
    void DoWork() {
        std::cout << "Work in progress inside B";
    }
    bool IsRunning() {
        return true;
    }
};

class Server {
    IService* _service;
    Server(IService* service) : _service(service)
    { }

    // Error: this declaration has no storage class or type specifier
    // Compiler: MSVC 2017
    _service->DoWork();
};

【问题讨论】:

  • 在 C++ 中,class 是(组合)数据类型的定义(类似于struct)。它可能不直接包含语句。语句只能在函数中使用(包括成员函数)。
  • _service-&gt;DoWork(); 是类内部但任何函数外部的语句。无论你的类是否抽象,你都不能在 C++ 中做到这一点。
  • 为了将来参考,我们在 Stack Overflow 上碰撞旧的 Q/A 没有问题。 OTOH,您的问题与其他问题不同,因此将其作为一个单独的问题提出是正确的
  • 这与抽象类或依赖注入无关。

标签: c++


【解决方案1】:
  1. 在 C++ 中,类成员默认为私有。 您应该在virtual void DoWork() = 0; 之前指定public:

  2. 默认情况下,C++ 继承是私有的(使用 class 关键字时)。而不是: IService,请尝试: public IService。查看私有继承、受保护继承和公共继承之间的区别here

  3. _service-&gt;DoWork();的函数体在哪里?

【讨论】:

  • (1) 没有必要这样做。非虚拟接口函数通常会调用私有虚拟函数,它们仍然可以被覆盖。 (2) 仅在使用 class 关键字时。
  • @StoryTeller (2) 很好。至于(1),我假设他希望外人能够调用IService 中的每个函数。我认为这里需要public?还是我错了?
  • 哦,您的意思是公开 ISerivce 函数。是的,我同意。脑子打嗝,抱歉。
  • @raymai97 天啊!我错过了 C++ 的功能和基础知识。这对我来说真的是一个非常愚蠢的错误。对于这类问题,我真的很抱歉。在进一步发布之前,我肯定会仔细检查任何代码。最后非常感谢。
【解决方案2】:

我相信这就是你想要的:

#include <iostream>
using namespace std;

struct IService {
    virtual ~IService() = default; // Remember about virtual dtor to avoid memory leaks!
    virtual void DoWork() = 0;
    virtual bool IsRunning() = 0;
};

class ClientA : public IService {
    void DoWork() {
        std::cout << "Work in progress inside A" << endl;
    }
    bool IsRunning() { 
        return true; 
    }
};

class ClientB : public IService {
    void DoWork() {
        std::cout << "Work in progress inside B" << endl;
    }
    bool IsRunning() {
        return true;
    }
};

class Server {
    IService* _service;
public:
    Server(IService* service) : _service(service)
    { }

    void doStuff() {
        _service->DoWork();
    }
};

int main() {

    ClientA a;
    ClientB b;
    Server sa(&a), sb(&b);
    cout << "ServerA: " << endl;
    sa.doStuff();
    cout << "ServerB: " << endl;
    sb.doStuff();
    return 0;
}

Ideone

您需要熟悉 C++ 中访问说明符的概念。见here

【讨论】:

  • 这是我最糟糕的事情之一,我错过了 C++ 的功能和基础知识。对我来说,这是一个很好的学习,我是如何犯下这个愚蠢的错误的。感谢您的友好和快速的支持。这几天我在 C# 概念上徘徊,然后回到 C++ 进行一些快速演示实现,看看我做了什么。太可惜了。
猜你喜欢
  • 1970-01-01
  • 2015-09-12
  • 1970-01-01
  • 2023-02-10
  • 2021-09-01
  • 2023-03-06
  • 2011-05-13
  • 1970-01-01
相关资源
最近更新 更多