无名结构体可以继承吗?

34
以下内容看起来像编译错误:
struct : Base { };

然而,当使用[1]时,它似乎是有效的:

#include <iostream>
using namespace std;

template<bool B>
struct A 
{
    struct : std::integral_constant<bool, B> {
    } members;
};

int main()
{
    A<true> a;    
    cout << a.members.value << endl;
    return 0;
}

C++中,未命名结构体可以继承吗?这样做有什么用处的例子吗?


[1] 免责声明:我并不是在假装所提供的例子有用。我很少使用未命名结构体,而且当我使用它们时,通常是将一些内置成员变量捆绑在一起,以便为类提供更清晰的接口。这个问题是从观察到memberspaces不需要命名结构体引起的。


第二个例子是有效的。它的用途还有待确定。 - StoryTeller - Unslander Monica
1
@StoryTeller:https://ideone.com/CWXUkv - lorro
@lorro 哇,这是一个相当悠久的回忆。虽然这个技巧很不错,但在我看来,std::tie才是更好的方法。 - StoryTeller - Unslander Monica
@StoryTeller:我并不喜欢std::tie,因为它要求你首先构造一个可能无效的对象。如果它是一个资源,如果我们没有默认构造函数,如果它需要时间/分配来构造呢?换句话说,我希望有一天我们可以在任何地方声明变量,包括在std::tie(或make tie)内部。这不会比在for/if/while内部更糟糕... - lorro
@lorro,好消息,这似乎已经被纳入C++17了。http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0144r0.pdf - StoryTeller - Unslander Monica
耶!:) 尽管我不喜欢这种语法,但它是一个巨大的飞跃。 - lorro
2个回答

43

无名类可以继承。例如,在必须继承才能覆盖虚函数但永远不需要超过一个类实例的情况下非常有用,而且您不需要引用派生类型,因为对基本类型的引用就足够了。

这里是一个示例:

#include <iostream>
using namespace std;

struct Base {virtual int process(int a, int b) = 0;};
static struct : Base {
    int process(int a, int b) { return a+b;}    
} add;
static struct : Base {
    int process(int a, int b) { return a-b;}    
} subtract;
static struct : Base {
    int process(int a, int b) { return a*b;}    
} multiply;
static struct : Base {
    int process(int a, int b) { return a/b;}    
} divide;

void perform(Base& op, int a, int b) {
    cout << "input: " << a << ", " << b << "; output: " << op.process(a, b) << endl;
}

int main() {
    perform(add, 2, 3);
    perform(subtract, 6, 1);
    perform(multiply, 6, 7);
    perform(divide, 72, 8);
    return 0;
}

这段代码创建了 Base 的四个匿名派生类 - 每个操作对应一个。当这些派生类的实例被传递给 perform 函数时,会调用正确的重载函数。请注意,perform 函数不需要知道任何具体类型 - 只需使用基类类型和虚函数即可完成该过程。

运行上述代码的输出如下:

input: 2, 3; output: 5
input: 6, 1; output: 5
input: 6, 7; output: 42
input: 72, 8; output: 9

在ideone上的演示。


9

你的第一个例子没有声明任何东西,它展示了对匿名结构体的尝试(这是不允许的 - 7/3),而不是无名结构体(是允许的)。

C++11标准中的9/1语法似乎允许无名类有一个基类,所以我认为你的第二个例子是可以的。


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