【问题标题】:how to design overloaded member functions with const and volatile while designing API?在设计 API 时如何设计带有 const 和 volatile 的重载成员函数?
【发布时间】:2023-03-07 08:11:01
【问题描述】:

假设您正在编写一个小型库或将分发给其他程序的 API, 这意味着您永远不知道其他程序员将如何创建对象:这样的对象是 const、volatile、const volatile 还是只是一个普通对象。

通常,当我们声明某个类时,我们会这样做:

class A // THIS CLASS DOES NOT SUPPORT ANYTHING
{
public:
    int get() { return x; }
private:
    int x;
};

但是,如果您希望您的类支持 const 对象,您将使用 const 限定符重载成员函数:

class B // THIS CLASS SUPPORTS CONST OBJECTS
{
public:
    int get() { return x; }
    int get() const { return x; }
private:
    mutable int x;
};

也许我们还想为我们的类支持 volatile 但不支持 const:

class C // THIS CLASS SUPPORTS VOLATILE OBJECTS
{
public:
    int get() { return x; }
    int get() volatile { return x; }
private:
    int x;
};

但是如果用户将使用 const 或 volatile 或 如果用户将同时使用 volatile 和 const 的对象怎么办? 那么我们也应该添加对它的支持!

class D // THIS CLASS SUPPORTS CONST, VOLATILE AND CONST VOLATILE OBJECTS
{
public:
    int get() { return x; }
    int get() const { return x; }
    int get() volatile { return x; }
    int get() const volatile { return x; }
private:
    mutable int x;
};

现在让我们看看为什么我们希望我们的类有这 4 个重载:

// EXAMPLE
int main()
{
    // figure 1
    const A a ;
    a.get(); // ERROR

    // figure 2
    volatile B b;
    b.get(); // ERROR

    // figure 3
    const volatile C c;
    c.get(); // ERROR

    // figure 4 where we finaly created a super class capable of anything!!
    const volatile D d;
    d.get(); // NOW IS OK!

    cin.ignore();
    return 0;
}

在最后一个例子中(图 4),我们可以证明我们的类能够被任何类型 这意味着其他程序员在创建您的类的 volatile、const 或 volatile const 对象时不会有问题!

我的问题是: 将每种方法重载四次是一种好的设计实践吗? 如果不是,为什么不呢?

如果我们的类有 20 个方法,那么当你重载它们时,它实际上会有 80 个方法!

编辑:

现实世界的 API 类会做这样的事情吗? 如果没有,那么如果假设我们有这样的需求,我们将如何创建该类的 volatile 或 const volatile 对象。

【问题讨论】:

  • 拥有const 对象是可行的,但我怀疑volatile 会有很多用途。此外,对于简单的 getter 之类的事情,我总是将我的方法设为 const。
  • 正如你所说:“我怀疑 volatile 会有很多用途”,至少其中一个可能想要,“我总是让我的方法成为 const”,如果该方法必须更改内部怎么办成员?所有方法都不能是 const,这样的类将是无用的:D
  • 我的意思是我总是使用简单的非修改方法,const。 :)

标签: c++ api


【解决方案1】:

我的看法是,在现实世界中:

  1. Volatile 没有被广泛使用,当它被广泛使用时,它总是修改基本类型。但绝不是对象,因此您永远不需要重写 volatile 成员函数。

  2. const 应该添加到成员函数中,而不是考虑 const 客户端代码是否需要它,而是考虑成员函数所做的操作是否在概念上是恒定的。这就是所谓的const正确性:

    一个。首先,该函数应该只做一件事。也许是一件复杂的事情,但可以描述为一个单一的概念。

    b.然后,问问自己函数所做的这件事是否会改变对象的可观察状态。如果是这样,那么函数不应该是常数。如果不是,则将其声明为常量。

当一个客户端代码想要使用你的类时,当它不允许修改对象的状态时,它会有一个const引用,一切都会正常工作。

请注意,我说的是对象的可观察状态,而不是成员变量的实际内容:这是一个实现细节。

【讨论】:

  • 有时,指向对象的指针是可变的(可变的最常用于内置类型),这并不要求您的方法是可变的。我从未见过这些 volatile 修饰符的用途(当然drdobbs.com/cpp/184403766 除外)。
  • @AlexandreC Al​​exandrescu 技术是对一种几乎无用的语言功能的巧妙滥用。太酷了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-31
  • 2011-04-10
相关资源
最近更新 更多