多重继承和单例设计模式

Multiple inheritance and singleton design pattern

我设置了以下 class 层次结构,并希望调用 non-singleton 基础 object OtherBaseprint() 函数,其中turn 从 child class 之一调用 printSymbol(),在本例中为 SingletonChild。我知道这是一个复杂且看起来有些不必要的层次结构和做事方式,但这是一项任务,我必须以这种方式完成。

我的问题举例如下:

#include <iostream>
using namespace std;

class Object
{
    virtual void print() = 0;
};

class SingletonBase : public Object
{
private:
    static SingletonBase* theOnlyTrueInstance;
protected:
    SingletonBase()
    {
        if(!theOnlyTrueInstance)
            theOnlyTrueInstance = this;
    }
    virtual ~SingletonBase(){}
public:
    static SingletonBase* instance()
    {
        if (!theOnlyTrueInstance) initInstance();
        return theOnlyTrueInstance;
    }
    void print()
    { cout<<"Singleton"<<endl; }
    static void initInstance()
    { new SingletonBase; }
};

SingletonBase* SingletonBase::theOnlyTrueInstance = 0;

class OtherBase : public Object
{
public:
    virtual string printSymbol() = 0;
    void print()
    { cout<<printSymbol(); }
};

class SingletonChild : public SingletonBase , public OtherBase
{
public:
    string printSymbol()
    {
        return "Test";
    }
    static void initInstance()
    { new SingletonChild; }
};

int main() {
    SingletonChild::initInstance();
    OtherBase* test = (OtherBase*) SingletonChild::instance();
    test->print();
    return 0;
}

如何让实例 test 调用单基 class OtherBaseprint 函数而不是单例基 class SingletonBase?

我试过test->OtherBase::print(),但是没用。

SingletonChildSingletonBase 继承它的 instance 方法,它返回指向 SingletonBase.
的指针 所以调用 SingletonChild::instance(); 会给你一个 SingletonBase*,你不能简单地转换为 OtherBase*

先尝试将其转换为 SingletonChild*,然后再转换为 OtherBase*:

OtherBase* test = (OtherBase*)((SingletonChild*)SingletonChild::instance());

然后像这样调用print方法:test->print();

参见code on ideone

编辑:

你也可以这样实现:

SingletonChild* test = (SingletonChild*)SingletonChild::instance();
test->OtherBase::print();

也见 this method in action

@MuhammadAhmad 的回答基本正确。我想补充一点,这里的主要问题是 C 风格的转换允许你做一些你真的不想做的事情。因为您不能将 SingletonBase 静态转换为 OtherBase,C 风格的转换正在执行 reinterpret_cast,并且在结果指针上调用 print() 是未定义的行为.如果你使用了 static_cast,你会得到一个错误:

OtherBase* test = static_cast<OtherBase*>(SingletonChild::instance());

error: invalid static_cast from type ‘SingletonBase*’ to type ‘OtherBase*’

这可能让您意识到您需要做一些不同的事情。例如,您可以使用 dynamic_cast 像这样向侧面施法。

您想要做的是将 SingletonBase* 类型的对象转换为类型 OtherBase*,这 不可能 因为 SingletonBase 不派生来自 OtherBase。如果您使用 dynamic_cast 而不是旧的、已弃用的 C 风格转换,您会立即意识到这种情况。

解决该问题需要修改代码如下:

class Object
{
    virtual void print() = 0;
};

class SingletonBase : public Object
{
private:
    static Object* theOnlyTrueInstance;
protected:
    SingletonBase()
    {
        if(!theOnlyTrueInstance)
            theOnlyTrueInstance = this;
    }
    virtual ~SingletonBase(){}
public:
    static Object* instance()
    {
        if (!theOnlyTrueInstance) initInstance();
        return theOnlyTrueInstance;
    }
    void print()
    { cout<<"Singleton"<<endl; }
    static void initInstance()
    { new SingletonBase; }
};

Object* SingletonBase::theOnlyTrueInstance = 0;

class OtherBase : public Object
{
public:
    virtual string printSymbol() = 0;
    void print()
    { cout<<printSymbol(); }
};

class SingletonChild : public SingletonBase , public OtherBase
{
public:
    string printSymbol()
    {
        return "Test";
    }
    static void initInstance()
    { new SingletonChild; }
};

int main() {
    SingletonChild::initInstance();
    OtherBase* test = dynamic_cast<OtherBase*>(SingletonChild::instance());
    test->print();
    return 0;
}

您应该避免 C 风格的转换,因为您最终可能会像操作对象一样操作对象。