使用 "struct S" 或 "S" 作为类型名之间的区别



C语言中结构化类型的名称Sliststruct S

在c++中也可以使用struct S作为类型名,而不是通常的

S
struct S {};
struct S s1; // also ok in C++
S s2; // normal way in C++

因此,假设在c++中使用struct SS作为类型名是一个品味问题;-)

但是在下面的例子中,有一些地方不允许使用struct S:

struct S1 {
S1(int x = 0) : x{x} {}
int x{};
};
typedef S1 S2;
template<typename T>
auto foo(T a) {
//    T::_; // T is deduced to `S` in all cases
return S1{a};
//    return struct S1{a}; // NOK
}
int main() {
//    foo(struct S1{i}); // NOK

S1 s1;
foo(s1);

struct S1 s2{2};
foo(s2);

foo(1);
//    struct S2 s20; // NOK
S2 s21;    
}
谁能给我解释一下这种不对称是怎么回事?看起来struct S不允许在需要作为表达式一部分的函数调用的地方使用。但是,如果类型S也可以写成struct S,那么使用struct S{}作为函数调用也应该是可以的。

允许在c++中编写struct S1 s1;有一个原因:与C兼容。C允许您同时拥有一个叫做S1的函数,所以struct S1是一个显式消歧。c++也允许这样做,只用于向后兼容

然而,在向后兼容性不适用的上下文中,c++不适用。例如,C没有构造函数。

这个问题还有一个令人困惑的地方:

typedef S1 S2;
struct S2 s2;

S2不是struct名称,而是别名,不能在别名前加上struct

的假设是,在c++中使用struct SS作为类型名是一个品味问题;-)

上面的假设是错误的,因为它有例外(正如你的例子中所指出的),原因更多的是与C兼容性有关,而不是品味问题。

关键是当我们可以/不可以使用struct S1代替S1时,有一些规则。假设我们总是可以用struct S1来代替S1是错误的。


返回语句的操作数应该是表达式,但struct S1{a}不是表达式,因此不能在返回语句中使用:

//-----vvvvvvvvvvvv----> operand is not an expression
return struct S1{a};

包含struct S1的表达式看起来像:

return (struct S1)a;

也有情况(s),当我们需要使用struct S1和使用S1将不工作。下面给出了一个人为的例子:

struct S1 
{

};
int S1() 
{
std::cout<<"function called"<<std::endl;
return 5;
}
int main() 
{
//S1 s; // ERROR: This won't work unless we use struct S1

struct S1 s2; //WORKS
}

class-key类或结构体仅在声明中使用。构造函数和析构函数使用class-name命名为函数。

例如在下面的声明

struct A
{
A() = default;
~A() = default;
};

构造函数和析构函数看起来像没有显式返回类型的函数声明。

这样的记录

struct A
{
struct A() = default;
struct ~A() = default;
};

无效。遇到关键字struct,编译器会认为这些记录是不正确的声明。

我认为在幕后有一种避免可能的歧义的愿望。例如这个结构

struct A()

看起来像一个函数类型,没有参数,返回类型是struct a。或者下面的记录

struct A {}

看起来像一个结构定义。

注意,使用一个详细的名称也会在给定的作用域中引入一个新的类型。考虑以下代码片段

struct A {};
int main()
{
struct A;
struct A { int x; };
}

记录struct A;在main的块作用域中引入了一个新类型,该类型隐藏了全局命名空间中引入的相同名称的结构。

相关内容

  • 没有找到相关文章

最新更新