小编Joh*_*ien的帖子

CRTP 相对于抽象类的优势?

我对“奇怪的重复模板模式”的概念很陌生,我正在此处阅读有关其潜在用例的信息。

在那篇文章中,作者描述了一个简单的情况,其中我们有两个或多个具有一些通用功能的类:

class A {
public:
  int function getValue() {...}
  void function setValue(int value) {...}

  // Some maths functions
  void scale() {...}
  void square() {...}
  void invert() {...}
}

class B {
public:
  double function getValue() {...}
  void function setValue(double value) {...}

  // Some maths functions
  void scale() {...}
  void square() {...}
  void invert() {...}
}
Run Code Online (Sandbox Code Playgroud)

作者认为,我们可以使用 CRTP,而不是在每个类中重复通用功能:

template <typename T>
struct NumericalFunctions
{
    void scale(double multiplicator);
    void square();
    void invert();
};

class A : public NumericalFunctions<A>
{ …
Run Code Online (Sandbox Code Playgroud)

c++ abstract-class crtp

8
推荐指数
1
解决办法
2555
查看次数

是否可以在 Exception 对象中存储有关错误的信息?

我一直在阅读 C++ 中的异常及其优点和缺点,但我还没有遇到任何人提到我真正喜欢它们的两件事:它们允许我扩展错误的定义(扩展到超过只是作为字符串的错误消息),并且它们允许我在异常处理程序和抛出程序之间定义一个契约:

“如果我要处理这种特殊类型的错误,我将需要你的这个,这个和那个。”

我没有在任何文章、论坛和博客文章中看到这一点,无论是赞成还是反对。这让我怀疑我对异常的看法以及如何使用它们可能是错误的。

为了澄清,这里有一个我使用异常的例子:

程序与 USB 设备通信(它向设备发送命令并期待它的特定响应)。在响应命令时,此 USB 设备有时会以意想不到的方式运行。在这种情况下,程序会抛出UnexpectedResponseFromDevice异常。此异常的处理程序需要的不仅仅是一条错误消息才能完成其工作。例如,它可能需要知道发生错误时我们向设备发送的命令,和/或设备所处的状态。我使用我的UnexpectedResponseFromDevice类的定义来明确规定处理错误所需的内容例外。请参阅下面的粗略想法。

class UnexpectedResponseFromDevice : public std::exception
{
private:
    Command command;
    DeviceState deviceState;
    std::string msg;

public:
    UnexpectedResponseFromDevice(std::string msg, Command command, DeviceState deviceState, ...)
    Command getCommand();
    DeviceState getDeviceState();
};
Run Code Online (Sandbox Code Playgroud)

这就是我所说的“在异常处理程序和抛出程序之间定义一个契约”的意思。为了抛出异常,需要提供这些东西(在这种情况下是命令、设备状态和消息)。

这是异常的可接受用例吗?我可以将处理异常所需的其他信息存储在异常对象中吗?这是可以接受的,但一个坏主意吗?如果是,请解释原因。

c++ exception

8
推荐指数
1
解决办法
202
查看次数

使用 std::Optional 使移动构造函数/分配中的 RAII 对象无效

假设我有一个 RAII 类,其实例永远不应该被复制:

class Session {

public:
    Session(); // Allocates a resource and sets generates a unique Session::id. 
    ~Session(); // Frees the resource

    Session(const Session&) = delete;
    Session& operator = (Session&) = delete;

private:
  std::uint32_t id;
}
Run Code Online (Sandbox Code Playgroud)

鉴于我不能允许复制,我想允许移动,所以我需要实现移动构造函数和移动赋值运算符,但我不确定应该如何处理Session::id移动的实例。

我可以:

  1. 将其设置为某个已知无效的值(可能将类型更改为有符号 int 并用作-1无效值)
  2. 使用类似的东西std::optional并将其设置为std::nullopt使其无效。

这些选项中哪一个(如果有的话)是正确的?

c++ raii c++20 stdoptional

2
推荐指数
1
解决办法
152
查看次数

标签 统计

c++ ×3

abstract-class ×1

c++20 ×1

crtp ×1

exception ×1

raii ×1

stdoptional ×1