此工厂功能有什么问题?

What is the issue with this factory function?

本文关键字:问题 什么 工厂 功能      更新时间:2023-10-16

在下面的代码中,我编写了一个工厂方法来创建类继承中的类型对象。


#include <iostream>
#include <memory>
using namespace std;
enum Type {
_Base, _A, _B, _C
};
class Base{
private:
Type type = _Base;
public:
virtual Type getType(){
return type;
}};
class A : public Base{
private:
Type type = _A;
public:
using Base::Base;
};
class B : public Base{
private:
Type type = _B;
public:
using Base::Base;
};
class C : public Base{
private:
Type type = _C;
public:
using Base::Base;
};
shared_ptr<Base> letterFactory(Type which){
shared_ptr<Base> base = make_unique<Base>(Base());
switch (which){
case _A:
base = make_unique<Base>(A());
case _B:
base = make_unique<Base>(A());
case _C:
base = make_unique<Base>(C());
}
return base;
}

int main(){
shared_ptr<Base> instanceOfA = letterFactory(_A);
cout << instanceOfA->getType() << endl;
shared_ptr<Base> instanceOfB = letterFactory(_B);
cout << instanceOfB->getType() << endl;
shared_ptr<Base> instanceOfC = letterFactory(_C);
cout << instanceOfC->getType() << endl;
return 0;
};

输出为

0
0
0

如何进行输出

1
2
3

你的工厂有点缺陷,你的getType()函数在派生类中没有被重写。我猜你想做一些类似的事情:

#include <iostream>
#include <memory>
using namespace std;
enum Type {
_Base, _A, _B, _C
};
class Base{
public:
virtual ~Base() = default;
virtual Type getType() const {
return _Base;
};
};
class A : public Base{
public:
virtual Type getType() const override {
return _A;
};
};
class B : public Base{
public:
virtual Type getType() const override {
return _B;
};
};
class C : public Base{
public:
virtual Type getType() const override {
return _C;
};
};
unique_ptr<Base> letterFactory(Type which){
switch (which){
case _Base:
return make_unique<Base>();
case _A:
return make_unique<A>();
case _B:
return make_unique<B>();
case _C:
return make_unique<C>();
}
return nullptr;
}

int main(){
shared_ptr<Base> instanceOfA = letterFactory(_A);
cout << instanceOfA->getType() << endl;
shared_ptr<Base> instanceOfB = letterFactory(_B);
cout << instanceOfB->getType() << endl;
shared_ptr<Base> instanceOfC = letterFactory(_C);
cout << instanceOfC->getType() << endl;
return 0;
};

请注意,我们完全删除了type成员,而是正确覆盖了getType()函数。此外,像这样的工厂函数通常会返回unique_ptr(如果您真的愿意,可以隐式转换为shared_ptr(。

您的Base类有一个成员type和一个返回成员type值的虚拟成员函数getType()。您的类ABC派生自Base。这意味着它们都有一个Base子对象。该子对象包含成员Base::type。此外,它们还添加了另一个成员type,然后从未被任何东西使用过。此外,它们都不会覆盖getType方法。所以每当你打电话

instanceOfX->getType()

即使instanceOfX指向其中一个派生类的实例,由于没有一个派生类覆盖getType,你最终会调用Base::getType,这将返回Base::type的值,它总是_Base...

你真正想要的可能是类似的东西:

struct Base
{
virtual Type getType() const = 0;
protected:
Base() = default;
Base(Base&&) = default;
Base(const Base&) = default;
Base& operator =(Base&&) = default;
Base& operator =(const Base&) = default;
~Base() = default;
};
class A : public Base
{
public:
Type getType() const override { return _A; }
};
class B : public Base
{
public:
Type getType() const override { return _B; }
};
class C : public Base
{
public:
Type getType() const override { return _C; }
};

请注意,这几乎可以肯定是糟糕的设计。这种getType方法的唯一用途是,客户端代码可以找出它所获得的Base*指向的对象的具体类型。如果您需要此信息,您的设计违反了利斯科夫替换原则......

除此之外,请注意_Base_A_B_C是保留名称 [lex.name]/3,您不应该在C++代码中使用...

我稍微重构了一下您的代码,只是为了应用一些最佳实践:

  • 使用enum class而不是原始enum因为enum class表示作用域枚举类型,并且它也是强类型的,这意味着您无法轻松地将其转换为整数作为原始enum(这就是我们有to_integral模板函数的原因(
  • 不希望使用using namespace std;,因为它将整个 std 命名空间导入到程序的当前命名空间中
  • 另外,我认为您想使用std::make_shared而不是std::make_unique
#include <memory>
#include <iostream>
enum class Type : int {
_Base = 0,
_A    = 1,
_B    = 2,
_C    = 3
};
class Base{
private:
Type type = Type::_Base;
public:
virtual Type getType(){
return type;
}
};
class A : public Base{
private:
Type type = Type::_A;
public:
virtual Type getType() override {
return type;
}
};
class B : public Base{
private:
Type type = Type::_B;
public:
virtual Type getType() override {
return type;
}
};
class C : public Base{
private:
Type type = Type::_C;
public:
virtual Type getType() override {
return type;
}
};
std::shared_ptr<Base> letterFactory(Type which){
switch (which){
case Type::_A:
return std::make_shared<A>();
case Type::_B:
return std::make_shared<B>();
case Type::_C:
return std::make_shared<C>();
default:
return std::make_shared<Base>(Base());
}
}
template <typename Enum>
constexpr typename std::enable_if<std::is_enum<Enum>::value,
typename std::underlying_type<Enum>::type>::type
to_integral(Enum const& value) {
return static_cast<typename std::underlying_type<Enum>::type>(value);
}
int main(){
std::shared_ptr<Base> instanceOfA = letterFactory(Type::_A);
std::cout << to_integral(instanceOfA->getType()) << std::endl;
std::shared_ptr<Base> instanceOfB = letterFactory(Type::_B);
std::cout << to_integral(instanceOfB->getType()) << std::endl;
std::shared_ptr<Base> instanceOfC = letterFactory(Type::_C);
std::cout << to_integral(instanceOfC->getType()) << std::endl;
return 0;
};

现场示例