如何在C ++中使用智能指针实现接口隔离原则?

时间:2019-07-03 06:39:42

标签: c++ c++11 smart-pointers solid-principles interface-segregation-principle

我来自Delphi和C#背景,因此我从他们的角度理解接口。我从事C ++已有几年了,但仍从其角度学习接口。

在我的应用程序中,我需要一个实现多个接口的类(即,继承多个纯抽象类)来指示每个类支持的各种行为。这不完全是ISP,但是它足够接近以至于是同样的问题。

行为接口不会相互继承。没有层次。

Delphi和C#无需费劲就可以做到这一点,但我试图弄清楚这是如何在C ++中完成的。 (此外,目前,我仅限于C ++ 11。)

我已经研究了dynamic_pointer_cast,static_pointer_cast,但是它们需要继承层次结构。

我看过reinterpret_pointer_cast,但是在C ++ 11中不可用。

我曾尝试使用行为接口继承的根接口(类似于COM中的IUnknown或Delphi中的IInterface),创建继承层次结构,但随后遇到了钻石问题。

我已经看到一些关于在基本接口中添加方法以返回对每个行为接口的引用的建议,但这是我确实不想要的一种耦合,因为稍后可能需要添加其他行为和类来实现它们

这是一些我尚未编译的代码,显示了我要执行的操作的简单示例。

class IBase
{
public:
    virtual void DoBaseStuff() = 0;
}

class IBehaviorA
{
public:
    virtual void DoBehaviorA() = 0;
}

class IBehaviorB
{
public:
    virtual void DoBehaviorB() = 0;
}

class Base : public IBase
{
public:
    Base()  {}
    virtual ~Base() {}
    virtual void DoBaseStuff() { /* ... */ }
}

class JustA : public IBase, public IBehaviorA
{
public:
    JustA() {}
    virtual ~JustA() {}
    virtual void DoBaseStuff() { /* ... */ }
    virtual void DoBehaviorA() { /* ... */ }
}

class JustB : public IBase, public IBehaviorB
{
public:
    JustB() {}
    virtual ~JustB() {}
    virtual void DoBaseStuff() { /* ... */ }
    virtual void DoBehaviorB() { /* ... */ }
}

class AandB : public IBase, public IBehaviorA, public IBehaviorB
{
public:
    AandB() {}
    virtual ~AandB() {}
    virtual void DoBaseStuff() { /* ... */ }
    virtual void DoBehaviorA() { /* ... */ }
    virtual void DoBehaviorB() { /* ... */ }
}

void ProcessAllBehaviorA(std::vector<std::shared_ptr<IBase>> bases)
{
    for (auto& base : bases)
    {
        std::shared_ptr<IBehaviorA> behaviorA
                    = SOME_KIND_OF_CAST<IBehaviorA>(base);

        if (behaviorA != nullptr)
        {
            behaviorA->DoBehaviorA();
        }
    }
}

void main()
{
    std::vector<std::shared_ptr<IBase>> bases;

    bases.push_back(std::shared_ptr<IBase>(new Base()));
    bases.push_back(std::shared_ptr<IBase>(new JustA()));
    bases.push_back(std::shared_ptr<IBase>(new JustB()));
    bases.push_back(std::shared_ptr<IBase>(new AandB()));

    ProcessAllBehaviorA(bases);
}

我试图弄清楚在ProcessAllBehaviorA方法中SOME_KIND_OF_CAST占位符的位置。

我确信我不能成为第一个尝试这样做的人。

其他人如何使用C ++中的智能指针来实现接口隔离原理(或类似的模式,如我的)?

1 个答案:

答案 0 :(得分:4)

  

我已经研究了dynamic_pointer_cast,static_pointer_cast,但是它们需要继承层次结构。

您的代码确实具有继承层次结构,因此CREATE PROCEDURE GENERATINGN ( IN p_docentryt NVARCHAR(50) ) LANGUAGE SQLSCRIPT AS BEGIN SELECT cast("ItemCode" || '-' || NEWUID() as nvarchar(50)) AS "UNIQUEIDENTIFIER" FROM "OITM" WHERE "T0"."DocEntry" = p_docentryt; END; 可以正常工作!我已经在您的代码中添加了一些行为,并且可以按预期工作。

std::dynamic_pointer_cast

输出:

#include <memory>
#include <vector>
#include <iostream>

class IBase
{
public:
    virtual void DoBaseStuff() = 0;
};

class IBehaviorA
{
public:
    virtual void DoBehaviorA() = 0;
};

class IBehaviorB
{
public:
    virtual void DoBehaviorB() = 0;
};

class Base : public IBase
{
public:
    Base() {}
    virtual ~Base() {}
    virtual void DoBaseStuff() { /* ... */ }
};

class JustA : public IBase, public IBehaviorA
{
public:
    JustA() {}
    virtual ~JustA() {}
    virtual void DoBaseStuff() { /* ... */ }
    virtual void DoBehaviorA() { std::cout << "I am just A!" << std::endl; }
};

class JustB : public IBase, public IBehaviorB
{
public:
    JustB() {}
    virtual ~JustB() {}
    virtual void DoBaseStuff() { /* ... */ }
    virtual void DoBehaviorB() { /* ... */ }
};

class AandB : public IBase, public IBehaviorA, public IBehaviorB
{
public:
    AandB() {}
    virtual ~AandB() {}
    virtual void DoBaseStuff() { /* ... */ }
    virtual void DoBehaviorA() { std::cout << "I am A and B" << std::endl; }
    virtual void DoBehaviorB() { /* ... */ }
};

void ProcessAllBehaviorA(std::vector<std::shared_ptr<IBase>> bases)
{
    for (auto& base : bases)
    {
        std::shared_ptr<IBehaviorA> behaviorA
            = std::dynamic_pointer_cast<IBehaviorA>(base);

        if (behaviorA != nullptr)
        {
            behaviorA->DoBehaviorA();
        }
        else {
            std::cout << "Requested pointer does not implement A." << std::endl;
        }
    }
}

void main()
{
    std::vector<std::shared_ptr<IBase>> bases;

    bases.push_back(std::shared_ptr<IBase>(new Base()));
    bases.push_back(std::shared_ptr<IBase>(new JustA()));
    bases.push_back(std::shared_ptr<IBase>(new JustB()));
    bases.push_back(std::shared_ptr<IBase>(new AandB()));

    ProcessAllBehaviorA(bases);
}

通过这种方式,您在类定义的末尾错过了分号。