我将这些C ++类定义如下:
class A
{
public:
B *createB();
};
class B
{
public:
virtual void fun() = 0;
};
class B1 : B {/* ... */};
class B2 : B {/* ... */};
所以基本上B是一个抽象类,B1和B2是B的具体实现,A在其代码中的某处创建了一个B类实例。重要的是要注意 A不是工厂,A::createB
只是一个例子。
我希望能够在A初始化期间传递B的子类,因此可以在运行时根据需要创建前者的实例。例如:
A *a1 = /* sorcery here */;
A *a2 = /* another magic code */;
a1->createB(); // getting B1
a2->createB(); // getting B2
实现它的最佳方法是什么?是否可以没有使用模板?
基于回应,我最终得到了这个。谢谢!
class B
{
public:
virtual void fun() = 0;
virtual B *clone() = 0;
};
class B1 : public B
{
public:
virtual void fun()
{
std::cout << "B1" << std::endl;
}
virtual B *clone()
{
return new B1();
}
};
class B2 : public B {/* analogous to B1 */};
class A
{
public:
A(B *b) : b(b) {};
B *createB()
{
return b->clone();
}
private:
B *b;
};
A(new B1()).createB()->fun(); // prints "B1"
A(new B2()).createB()->fun(); // prints "B2"
答案 0 :(得分:4)
在B中实施clone()
方法。
创建时将B*
传递给A. A将以clone()
作为参数调用B B*
。
有关克隆的详细信息,请参阅问题Which situation will use clone in C++ and how to use it?,What's the best signature for clone() in C++?和How to write a clone method easily?等。
答案 1 :(得分:2)
您可以使用Prototype设计模式来实现此目的。通过A
B1
或B2
的实例,并将clone()
成员函数添加到B
,如下所示:
class B
{
public:
virtual void fun() = 0;
virtual B* clone() = 0; // B1::clone returns new B1; B2::clone returns new B2
};
A
存储在初始化期间传入的B
原型实例以供以后使用。如果以后需要创建新的B
,它会在原型上调用clone()
来获取正确类的实例。
答案 2 :(得分:0)
听起来像你想要abstract factory。
您可以看到示例here:
#include <iostream>
#include <string>
class Window
{
protected:
int width;
int height;
std::string toolkit;
std::string type;
Window(std::string usedToolkit, std::string windowType)
: toolkit(usedToolkit), type(windowType)
{}
public:
std::string getToolkit()
{
return toolkit;
}
std::string getType()
{
return type;
}
};
class GtkToolboxWindow : public Window
{
public:
GtkToolboxWindow()
: Window("Gtk", "ToolboxWindow")
{}
};
class GtkLayersWindow : public Window
{
public:
GtkLayersWindow()
: Window("Gtk", "LayersWindow")
{}
};
class GtkMainWindow : public Window
{
public:
GtkMainWindow()
: Window("Gtk", "MainWindow")
{}
};
class QtToolboxWindow : public Window
{
public:
QtToolboxWindow()
: Window("Qt", "ToolboxWindow")
{}
};
class QtLayersWindow : public Window
{
public:
QtLayersWindow()
: Window("Qt", "LayersWindow")
{}
};
class QtMainWindow : public Window
{
public:
QtMainWindow()
: Window("Qt", "MainWindow")
{}
};
/* This is the abstract factory. */
class UIFactory
{
public:
virtual Window* getToolboxWindow() = 0;
virtual Window* getLayersWindow() = 0;
virtual Window* getMainWindow() = 0;
};
/* Factory for Gtk toolkit */
class GtkUIFactory : public UIFactory
{
public:
Window* getToolboxWindow()
{
return new GtkToolboxWindow();
}
Window* getLayersWindow()
{
return new GtkLayersWindow();
}
Window* getMainWindow()
{
return new GtkMainWindow();
}
};
/* Factory for Qt toolkit */
class QtUIFactory : public UIFactory
{
public:
Window* getToolboxWindow()
{
return new QtToolboxWindow();
}
Window* getLayersWindow()
{
return new QtLayersWindow();
}
Window* getMainWindow()
{
return new QtMainWindow();
}
};
int main()
{
UIFactory* ui = 0;
/* Check what environment is running
and create appropriate factory. */
if (/* Gtk == */ true)
{
ui = new GtkUIFactory();
}
else
{
ui = new QtUIFactory();
}
/* Use the factory to build interface. */
Window* toolbox = ui->getToolboxWindow();
Window* layers = ui->getLayersWindow();
Window* main = ui->getMainWindow();
/* See what have we recieved. */
std::cout << toolbox->getToolkit() << ":"
<< toolbox->getType() << std::endl;
std::cout << layers->getToolkit() << ":"
<< layers->getType() << std::endl;
std::cout << main->getToolkit() << ":"
<< main->getType() << std::endl;
}