繁体   English   中英

多重继承和单例设计模式

[英]Multiple inheritance and singleton design pattern

我设置了以下类层次结构,并希望调用非单个基础对象OtherBaseprint()函数,该函数printSymbol()子类之一(在本例中为SingletonChild printSymbol()调用printSymbol() 我知道这是一种复杂且有些不必要的外观层次结构和处理方式,但这是一项任务,我需要以此方式进行处理。

我的问题的一个例子如下:

#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来调用一个基类OtherBase而不是Singleton基类SingletonBaseprint功能?

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

@MuhammadAhmad的答案基本上是正确的。 我想补充一点,这里的主要问题是C风格的强制转换允许您执行您确实不想执行的操作。 因为您不能将SingletonBase静态转换为OtherBase ,所以C样式转换将执行reinterpret_cast ,并且在结果指针上调用print()是未定义的行为。 如果您使用了static_cast ,那么将得到一个错误:

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

错误:从类型'SingletonBase *'到类型'OtherBase *'的static_cast无效

这可能使您意识到需要做一些不同的事情。 例如,您可以使用dynamic_cast这样横向投射。

SingletonChildSingletonBase继承其instance方法,该方法将返回指向SingletonBase的指针。
因此调用SingletonChild::instance(); 将为您提供SingletonBase* ,您不能简单地将其OtherBase*OtherBase*

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

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

然后像下面这样简单地调用print方法: test->print();

请参阅ideone上代码

编辑

您也可以这样实现:

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

实际也请参见此方法

您要尝试将类型为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风格的强制类型转换,因为您可能最终会像对待对象一样操纵对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM