多重继承和单例设计模式
Multiple inheritance and singleton design pattern
我设置了以下 class 层次结构,并希望调用 non-singleton 基础 object OtherBase
的 print()
函数,其中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 OtherBase
的 print
函数而不是单例基 class SingletonBase
?
我试过test->OtherBase::print()
,但是没用。
SingletonChild
从 SingletonBase
继承它的 instance
方法,它返回指向 SingletonBase
.
的指针
所以调用 SingletonChild::instance();
会给你一个 SingletonBase*
,你不能简单地转换为 OtherBase*
先尝试将其转换为 SingletonChild*
,然后再转换为 OtherBase*
:
OtherBase* test = (OtherBase*)((SingletonChild*)SingletonChild::instance());
然后像这样调用print
方法:test->print();
编辑:
你也可以这样实现:
SingletonChild* test = (SingletonChild*)SingletonChild::instance();
test->OtherBase::print();
@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 风格的转换,因为您最终可能会像操作对象一样操作对象。
我设置了以下 class 层次结构,并希望调用 non-singleton 基础 object OtherBase
的 print()
函数,其中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 OtherBase
的 print
函数而不是单例基 class SingletonBase
?
我试过test->OtherBase::print()
,但是没用。
SingletonChild
从 SingletonBase
继承它的 instance
方法,它返回指向 SingletonBase
.
的指针
所以调用 SingletonChild::instance();
会给你一个 SingletonBase*
,你不能简单地转换为 OtherBase*
先尝试将其转换为 SingletonChild*
,然后再转换为 OtherBase*
:
OtherBase* test = (OtherBase*)((SingletonChild*)SingletonChild::instance());
然后像这样调用print
方法:test->print();
编辑:
你也可以这样实现:
SingletonChild* test = (SingletonChild*)SingletonChild::instance();
test->OtherBase::print();
@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 风格的转换,因为您最终可能会像操作对象一样操作对象。