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

C++ 如何在C+;中使用智能指针实现接口隔离原则+;?,c++,c++11,smart-pointers,solid-principles,interface-segregation-principle,C++,C++11,Smart Pointers,Solid Principles,Interface Segregation Principle,我来自Delphi和C#的背景,所以我从他们的角度理解接口。我做C++已经有几年了,从它的角度来看仍然在学习接口。 在我的应用程序中,我需要实现多个接口的类(即继承多个纯抽象类)来指示每个类支持的各种行为。这并不完全是ISP的问题,但这已经足够接近于同一个问题了 行为接口不会相互继承。没有等级制度 delphi和C,这样做没有呼吸沉重,但我试图弄清楚这是如何在C++中完成的。(另外,目前我仅限于C++11。) 我已经研究了动态指针转换、静态指针转换,但它们需要继承层次结构 我看过reinter

我来自Delphi和C#的背景,所以我从他们的角度理解接口。我做C++已经有几年了,从它的角度来看仍然在学习接口。 在我的应用程序中,我需要实现多个接口的类(即继承多个纯抽象类)来指示每个类支持的各种行为。这并不完全是ISP的问题,但这已经足够接近于同一个问题了

行为接口不会相互继承。没有等级制度

delphi和C,这样做没有呼吸沉重,但我试图弄清楚这是如何在C++中完成的。(另外,目前我仅限于C++11。)

我已经研究了动态指针转换、静态指针转换,但它们需要继承层次结构

我看过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);
}
class-IBase
{
公众:
虚拟void DoBaseStuff()=0;
}
IBehaviorA类
{
公众:
虚空DoBehaviorA()=0;
}
IBehaviorB类
{
公众:
虚空DoBehaviorB()=0;
}
类库:公共IBase
{
公众:
Base(){}
虚拟~Base(){}
虚拟空DoBaseStuff(){/*…*/}
}
JustA类:公共IBase,公共IBehaviorA
{
公众:
JustA(){}
虚拟~JustA(){}
虚拟空DoBaseStuff(){/*…*/}
虚拟空DoBehaviorA(){/*…*/}
}
B类:公共IBase,公共IBehaviorB
{
公众:
JustB(){}
虚拟~JustB(){}
虚拟空DoBaseStuff(){/*…*/}
虚空DoBehaviorB(){/*…*/}
}
A级和B级:公共IBase、公共IBehaviorA、公共IBehaviorB
{
公众:
AandB(){}
虚拟~AandB(){}
虚拟空DoBaseStuff(){/*…*/}
虚拟空DoBehaviorA(){/*…*/}
虚空DoBehaviorB(){/*…*/}
}
void ProcessAllBehaviorA(标准::向量基)
{
用于(自动和基础:基础)
{
std::共享的ptr行为
=某种类型的铸造(基础);
if(behaviorA!=nullptr)
{
behaviorA->DoBehaviorA();
}
}
}
void main()
{
std::向量基;
Base.push_back(std::shared_ptr(newbase());
base.push_back(std::shared_ptr(new JustA());
base.push_back(std::shared_ptr(new JustB());
base.push_back(std::shared_ptr(new AandB());
过程行为(碱基);
}
我试图弄清楚在ProcessAllBehaviorA方法中某种类型的强制转换占位符的位置应该做什么

我确信我不可能是第一个尝试这样做的人

其他人如何使用C++中的智能指针实现接口隔离原则(或类似的模式)? 我已经研究了动态指针转换、静态指针转换,但它们需要继承层次结构

您的代码确实有继承层次结构,因此
std::dynamic\u pointer\u 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);
}

顺便说一句,您错过了类定义末尾的分号。

我认为不可能强制转换共享参数的类型,并且它仍然可以按预期工作,但在调用函数时,是什么阻止您强制转换指针呢?即,代替
std::shared\u ptr behaviorA=某种类型的演员(基本)
do
IBehaviorA*behaviorA=dynamic_cast(base.get())旁白:如果是覆盖,则首选
void DoBaseStuff()override
void DoBaseStuff()final
而不是
virtual void DoBaseStuff()
。请记住,在使用
dynamic\u cast
时,您几乎总是希望启用RTTI。并非所有项目都支持它。通常,向上转换和分析基类被认为是不好的做法。如果您手动执行分支,则polymorhism没有实际用途。
Requested pointer does not implement A.
I am just A!
Requested pointer does not implement A.
I am A and B