【问题标题】:Why use 'struct' keyword in class pointer declaration in C++为什么在 C++ 的类指针声明中使用“struct”关键字
【发布时间】:2019-12-26 19:27:07
【问题描述】:

在 C++ 中声明类指针变量时,何时以及为什么要使用 'struct' 关键字?

我在嵌入式环境中看到了这一点,所以我怀疑这是 C 语言的某种保留。我已经看到了很多关于在声明结构对象时何时使用“struct”关键字的解释,因为它与C 中的命名空间 (here),但我找不到任何人谈论为什么在声明类指针变量时可能会使用它。

例如,在 CFoo.h 中:

class CFoo
{
public:
    int doStuff();
};

inline Foo::doStuff()
{
    return 7;
}

然后在不同的班级:

void CBar::interesting()
{
    struct CFoo *pCFoo;

    // Go on to do something interesting with pCFoo...
}

【问题讨论】:

  • @πάνταῥεῖ 再一次,糟糕的骗局。那个是关于 C 的。这个问题是关于 C++ 的。区别是问题的全部意义。请停下来。
  • 把这个作为一个 C 问题的骗子关闭不是一个好主意。在 C 中,这纯粹是风格问题。
  • @Lundin 在 C++ 中,这是一个风格问题。在 C 中,这是强制性的。
  • @LightnessRacesinOrbit 如果您使用 typedef,则不会,这是迄今为止 C 中最常见的样式。
  • @Lundin 好吧,那是作弊!这个问题不是关于使用类型别名,而是关于使用类型的实际名称及其限制/约束/要求。是的,您可以使用类型别名来绕过 C 中的上述要求。是的,这非常常见。不过,作为旁注,像struct tm 这样的东西没有得到这种处理,所以它们也非常常见——即使在 C++ 代码中也是如此,哈哈

标签: c++ class variables scope elaboration


【解决方案1】:

很少有这样做的理由:它是 C 语言的一个错误,在这种情况下,程序员只是多愁善感——也许是为了追求可读性。也就是说,它可以用来代替前向声明。

在某些情况下,您可能需要消除歧义,但此处并非如此。需要消歧的一个例子是

class foo{};

int main()
{
    int foo;
    class foo* pf1;
    struct foo* pf2;
}

请注意,您可以交替使用classstruct。您也可以使用typename,这在使用模板时很重要。以下是有效的 C++:

class foo{};

int main()
{    
    class foo* pf1;
    struct foo* pf2;
    typename foo* pf3;
}

【讨论】:

  • 请注意,尽管foo 只是“一个类”,而不管您最初用于定义它的语法如何,VS 尤其倾向于警告关键字切换!
  • @LightnessRacesinOrbit:如果您使用struct 转发声明然后使用class 定义,MSVC 不会编译失败吗?
  • 无论是什么等同于-Werror,我确定是的:)
  • (真正的答案:我实际上不知道;可能!)
  • @Bathsheba 哦,是的,是worse than I thought - 忘了!
【解决方案2】:

这样做有两个原因。

第一个是如果我们要使用详细名称在范围中引入新类型。就是在这个定义中

void CBar::interesting()
{
    struct CFoo *pCFoo;

    // Go on to do something interesting with pCFoo...
}

新类型struct CFoo 被引入范围中,前提是它尚未声明。指针可能指向不完整的类型,因为指针本身就是完整的类型。

第二种情况是类的名称被函数或变量的声明隐藏。在这种情况下,我们再次需要使用详细的类型名称。

这里有一些例子

#include <iostream>

void CFoo( const class CFoo * c ) { std::cout << ( const void * )c << '\n'; }

class CFoo
{
public:
    int doStuff();
};


int main() 
{
    class CFoo c1;

    return 0;
}

或者

#include <iostream>

class CFoo
{
public:
    int doStuff();
};

void CFoo( void ) { std::cout << "I am hidding the class CGoo!\n"; }

int main() 
{
    class CFoo c1;

    return 0;
}

【讨论】:

    【解决方案3】:

    在 C 语言中,最常见的有两种不同的风格:

    • typedef struct { ... } s; 变量声明为 s name;
    • struct s { ... }; 变量声明为 struct s name;

    在C++中你不需要typedef来省略struct关键字,所以前一种风格更符合C++类型系统和类,是C++中最常见的风格。

    但是,在 C++ 中,当您实际上想首先使用 struct 而不是 class 时,在 C++ 中并没有很多情况 - 结构本质上是默认情况下所有成员都是公共的类。

    【讨论】:

    • “结构本质上是类,默认情况下所有成员都是公共的” Classes are classes are classes. C++ does not have structs.(尽管+1)
    • @LightnessRacesinOrbit 出于某种神秘的原因,曾一度鼓励将 STL 函子写成结构而不是类。尽管那很可能是在 C++98 之前的日子。
    • 我通常使用struct 来定义函子,因为它们倾向于有状态,所以我只需很少写private:(而不是@ 987654333@ 频繁),坦率地说,它只是“看起来更轻巧”(即使这是一个谎言)。但它们仍然是类:)
    • @LightnessRacesinOrbit 我想我曾从 2000 年出版的一本奇怪的小书“使用 C++ STL 设计组件”中找到它。作者 (Breymann) 给出了编写函子的奇怪理由as structs:“struct这个词保存了公共标签。一切都可以是公共的,因为类没有需要保护的数据。”这是真的,我想……他甚至在那时还称它为一堂课。
    • 嗯,如果我没看错的话,他的理由是“一切都可以公开,所以你可以使用结构”,就好像说“结构中的一切都必须公开”。事实是,这不是真的。
    【解决方案4】:

    这样做的原因可能很简单,因为不必包含不需要内容的头文件,除了宣布CFoo 命名了一个类型。这通常通过前向声明来完成:

    class CFoo;
    void f(CFoo*);
    

    但也可以即时完成:

    void f(struct CFoo*);
    

    【讨论】:

    • 为我的答案捏了一把。为美好的感觉投票!
    猜你喜欢
    • 1970-01-01
    • 2014-10-29
    • 1970-01-01
    • 2014-02-17
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    相关资源
    最近更新 更多