gpt4 book ai didi

c++ - 防止类在堆栈上实例化或作为数据成员实例化

转载 作者:行者123 更新时间:2023-11-27 23:31:53 24 4
gpt4 key购买 nike

我开始在 C++ (Visual Studio 2010) 中使用共享指针并遇到以下问题。

我正在编写一个新模块,它定义了一个接口(interface),告诉模块在特定条件下如何表现。是这样的(人工示例只是为了说明我的问题):

// Interface that should be implemented by user of the module
class RingAlert
{
public:
virtual void ring() = 0;
};

// Module that does something important
class Module
{
public:
Module (RingAlert &ringAlert) : m_ringAlert(ringAlert) {}
void dosomething(); // may call RingAlert::ring if something goes wrong.
private:
RingAlert &m_ringAlert;
};

为了方便模块的用户,并且因为 RingAlert 也可以传递给其他模块,我现在将其设为共享指针,如下所示:

typedef std::shared_ptr<RingAlert> RingAlertPtr;

class Module
{
public:
Module (RingAlertPtr ringAlert) : m_ringAlert(ringAlert) {}
void dosomething(); // may call RingAlert::ring if something goes wrong.
private:
RingAlertPtr m_ringAlert;
};

现在该模块的用户可以创建一个新的 RingAlert 实例并将其简单地传递给该模块,而无需将其保留在某个地方并在应用程序结束时将其删除。

如果应用程序做这样的事情,问题就开始了:

class MyRingAlert : public RingAlert
{
public:
virtual void ring() {std::cout << "ring ring" << std::endl;}
};

class Application
{
public:
private:
MyRingAlert m_myRingAlert;
};

// later, somewhere in application code
Module m(RingAlertPtr(&m_myRingAlert));

在此示例中,应用程序获取数据成员的地址并将其放入共享指针中。稍后在应用程序中,Module 的析构函数将删除共享指针,这将减少引用计数,然后将删除 环警报,不能删除,因为它是数据Application 类的成员。

我找到了一种防止共享指针删除实例的方法(使用 lambda,但也有一个使用函数的更简洁的解决方案):

Module m(RingAlertPtr(&m_myRingAlert,[](void *){});

虽然这解决了我的问题,但我对此并不完全满意,因为如果 Application 类在 Module 类之前被析构,它仍然会出现问题。

唯一好的解决方案似乎是强制应用程序的其余部分新建 RingAlert 的实例(或者实际上是实现 RingAlert 的类)。

这能做到吗?有没有办法阻止代码在堆栈上或作为数据成员实例化基类的子类?换句话说:如果要实例化基类的子类,我们可以强制更新它们吗?

最佳答案

这是一个根本性的缺陷——如果我想让我的主类继承并提供那个回调怎么办?你人为地限制它没有真正的优势。请改用 std::function

class Module {
public:
Module (std::function<void()> ringAlert) : Alert(ringAlert) {}
void dosomething() {
if (something) alert();
}
private:
std::function<void()> alert;
};

标准函数类型非常灵活且非常好用。

您还可以提供自定义销毁函数。

class Module {
public:
Module(interface* ptr, std::function<void(interface*)> destructor)
:pointer(ptr), destruct(destructor) {
}
~Module() {
if (destruct)
destruct(pointer);
}
void doSomething() {
if (condition)
pointer->ring();
}
private:
interface* pointer;
std::function<void(interface*)> destruct;
};

如果我在堆栈上分配,我会传递一个空函数对象。如果我在堆上分配,我会传递一个快速销毁 lambda。

关于c++ - 防止类在堆栈上实例化或作为数据成员实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4735778/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com