多重继承和单例设计模式
Multiple inheritance and singleton design pattern
我设置了以下类层次结构,并希望调用非单例基对象的print()
函数,该函数OtherBase
调用,该函数又调用其中一个子类的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
调用一个基类OtherBase
而不是单例基类SingletonBase
的print
函数?
我已经尝试过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
像这样横向投射。
SingletonChild
从SingletonBase
继承了它instance
方法,该方法返回指向SingletonBase
的指针。
所以打电话给SingletonChild::instance();
会让你得到一个SingletonBase*
,你不能简单地投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 样式的强制转换,因为您最终可能会像它们不是的东西一样操纵对象。
- 初学者C++线程安全单例设计
- 设计许多单例代码结构的更好方法
- C++单例模式代码无法运行,不知道为什么?
- 使用工厂模式实施单例
- 工厂模式和单例模式:未定义的引用
- C++:单例类设计(错误:未解析的外部符号)
- 使用静态和避免单例模式声明全局变量
- 如何在 c++ 中使用单例模式时编写 cmake 文件
- C++ 单例设计模式替代方案
- 可派生类的单例模式
- 这是单例模式的正确实现吗?
- 懒惰的初始化使用单例模式
- 单例设计模式 - 显式声明类外的构造函数
- 在单例设计模式中使用复制构造函数和赋值运算符
- 完美的单例设计模式
- 如何避免这种类似单例的设计模式
- 在什么情况下,单例设计模式可能会生成同一单例类的多个实例
- 不是全局单例设计模式
- 多重继承和单例设计模式
- 设计模式——在c++中,当实现(一组单例)直接从它们的编译单元在某个注册表中自注册时,它被称为什么?