易失性重载?

11

我听说volatile像const一样是重载的因素。

如果通过volatile参数进行函数重载, 那么什么情况下会调用volatile版本?

我无法想象何时会调用volatile版本。


已添加C++标签;如果您所讨论的不是这种语言,请编辑您的问题并提到这个相当重要的事实,然后进行适当的重新标记。 - Mat
2
这与 const 类似,如果您有一个带有 volatile 限定符的对象,则只能调用 volatile 函数。 - Alok Save
4
通常,几乎所有适用于 const 限定符的内容也适用于 volatile 限定符。标准通常将它们共同称为“_cv-qualifiers_”(即 const 和 volatile 的组合)。 - Mike Seymour
这里有一个有趣的使用(或者说滥用)volatile成员函数的例子,可以在编译时检查对象是否以线程安全的方式被访问。基本上,您通过volatile引用访问未锁定的对象,通过普通引用访问已锁定的对象,并且每个操作都有一个volatile重载,它首先获取锁。 - Mike Seymour
3个回答

10

以下是一个例子:

#include <iostream>

struct A {
    void foo() {
        std::cout << "in non-volatile" << std::endl;
    }
    void foo() volatile {
        std::cout << "in volatile" << std::endl;
    }
};

int main()
{
    A a;
    a.foo();
    volatile A b;
    b.foo();
}

b.foo()将调用volatile重载。如果struct A没有foovolatile重载,那么b.foo()将无效。


不要那么快。这个问题似乎是关于易失性参数的,而这些并不是重载的因素。 - Jirka Hanika
那对我来说并不是很清楚 - Pete已经发布了有关函数参数的答案。 - Mat
我对此没有意见,但是@Pete也没有给出完整的答案。也许我们应该合并一下。 - Jirka Hanika
为了做到这一点,我将您的好建议纳入了被接受的答案,并给您点了赞。 - Jirka Hanika
我在你的代码中加入了一个标准引用,希望你不介意 :) - Mat

8

在参数上可以使用Volatile关键字,但直接应用于参数时不会影响重载。然而,可以使用它来区分参数的类型。例如,以下写法是合法的:

void f(int &p) {}; //reference to int
void f(volatile int &p) {}; //reference to volatile int

这不是:

void f(int p) {};
void f(volatile int p) {};

原因在于第一个示例中引用的不是volatile,而是整数。在第二个示例中,两种类型都是整数,因此是相同类型。

还有一些volatile方法,它们类似于声明this为volatile。由于this是指针而不是包含类型本身,因此以下内容也是合法的:

void c::f(int p) {};
void c::f(int p) volatile {};

对于使用 const 进行重载也是一样的。

C++标准中与此相关的部分为§13.1 可重载声明。来自C++11草案n3290:

仅在 const 和/或 volatile 存在或不存在时不同的参数声明是等效的。也就是说,当确定正在声明、定义或调用哪个函数时,将忽略每个参数类型的const和volatile类型说明符。【例如:

typedef const int cInt;
int f(int);
int f(const int);          // redeclaration of f(int)
int f(int) { /* ... */ }   // definition of f(int)
int f(cInt) { /* ... */ }  // error: redefinition of f(int)

— 示例结束 ]

只有参数类型规范中最外层的const和volatile类型说明符才会被忽略;嵌套在参数类型规范中的const和volatile类型说明符是有意义的,并且可以用于区分重载函数声明124。特别地,对于任何类型T,T指针const T指针volatile T指针被视为不同的参数类型,同样地,T引用const T引用volatile T引用也是如此。

124) 当参数类型包括函数类型时,比如当参数类型是指向函数的指针时,内部函数类型的最外层参数类型规范中的const和volatile类型说明符也会被忽略。


3

编写一个测试程序来找出结果。

void func(const int& a)
{
    std::cout << "func(const)" << std::endl;
}

void func(const volatile int& a)
{
    std::cout << "func(const volatile)" << std::endl;
}

int main()
{
    const int a = 0;
    const volatile int b = 0;
    func(a);
    func(b);
    system("pause");
    return 0;
}

将输出:

func(const)
func(const volatile)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接