存储可以使用不同派生类型初始化的基类型成员变量时,请避免使用new
Avoid new when storing base-typed member variable that could be initialized with different derived types
我的代码结构如下,其中多个类实现Interface。在Example类中,我将一个指向Interface的指针和new()适当地存储在构造函数中(取决于此处未显示的构造函数参数)。我正在寻找避免在这种情况下使用new()的方法,但还没有找到解决方案。这样的事情最好的做法是什么?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
通常有两种方法,每种方法都有自己的优点。
如果A是在编译时真正定义的,那么处理这一问题的典型方法就是简单地使用模板类型:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
这有一些缺点。TemplateExample<A>
变得与TemplateExample<B>
无关,当T
没有遵循正确的接口时,错误消息非常迟钝,等等。好处是可以使用鸭子类型而不是接口类型,m_bar就是一个具体的实例。
另一种(有争议的更常见的)方法是进行以下
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
这有一个好处,如果你遵循一个可复制的模式,可以在运行时进行配置:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
请注意,您可以进一步扩展上述功能,使其具有克隆功能的移动变体。
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 为什么 std::make_shared 无法编译带有已删除运算符 new 的类型?
- 如何分配适合容纳 T 类型对象的缓冲区(可能过度对齐、可能有运算符 new 等)
- 在模板类中使用'new'类型安全吗?
- 在任何类类型上使用模板方法中的 new
- 如果在没有 new 运算符的情况下初始化,C++是否将类对象视为值类型
- C++内存 - 是否需要删除使用 'new' 创建的基元类型变量?
- c++:new返回一个类型,但编译正常
- 使用 new [] 在 C++ 中创建自定义 a 类型的动态数组
- 模板类的构造函数在使用 new 关键字时调用类型构造函数
- 何时正确定义放置新放置,以及调用放置 new 时现有类型会发生什么情况
- 存储可以使用不同派生类型初始化的基类型成员变量时,请避免使用new
- new int[M][N]的类型是什么?
- 如何为数组的类型调用 new 运算符
- 是否可以根据分配对象的类型特征覆盖全局 new 运算符?
- 使用new操作符在不知道对象类型的情况下将其复制到堆中
- 通过new[]分配n个字节,并用任何类型填充它
- 获取在new操作符中分配的对象类型