为什么Microsoft在新代码中使用结构而不是类?

Why is Microsoft using struct rather than class in new code?

本文关键字:结构 新代码 Microsoft 代码 为什么      更新时间:2023-10-16

所以通常我不会问这样的问题,因为它似乎是基于意见的,或者开始对编码实践进行某种口头战争,但我认为这里可能有一个我不明白的技术原因。

我正在查看 vcpkg(Microsoft正在创建的库打包管理器并且是"新"代码(的头文件中的代码,因为阅读代码通常是学习您不知道的东西的好方法。

我注意到的第一件事是使用using而不是typedef

"https://github.com/microsoft/vcpkg/blob/master/toolsrc/include/vcpkg/parse.h"中的代码段

template<class P>
using ParseExpected = ExpectedT<std::unique_ptr<P>, std::unique_ptr<ParseControlErrorInfo>>;

我以前没有以这种方式亲自使用过using,答案来自:C++11 中的"typedef"和"using"有什么区别?从本质上讲,using是执行此操作的新方法,其好处是它可以使用模板。所以Microsoft有充分的理由使用using而不是typedef

看着"https://github.com/microsoft/vcpkg/blob/master/toolsrc/include/vcpkg/commands.h",我注意到他们没有使用任何类。相反,它只是带有函数之类的命名空间。即:

namespace vcpkg::Commands
{
namespace BuildExternal
{
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet);
}
}

我猜其中一部分是调用语法看起来本质上就像类中的静态成员函数,因此代码执行相同,但可能会通过成为命名空间而不是类来节省一些开销。 (如果有人对此也有任何想法,那就太好了。

现在这一切的要点。为什么Microsoft在其命名空间中使用结构而不是类?

来自"https://github.com/microsoft/vcpkg/blob/master/toolsrc/include/vcpkg/parse.h"的代码段:

namespace vcpkg::Parse
{
/* ... Code I'm excluding for brevity ... */
struct ParagraphParser
{
ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {}
void required_field(const std::string& fieldname, std::string& out);
std::string optional_field(const std::string& fieldname) const;
std::unique_ptr<ParseControlErrorInfo> error_info(const std::string& name) const;
private:
RawParagraph&& fields;
std::vector<std::string> missing_fields;
};
}

在搜索stackoverflow时,我发现了一个老问题:为什么Microsoft使用struct for directX库而不是类? 答案本质上是,您不必将事情声明为默认公开,并且不必在底部添加注释方式说它是旧代码。

如果 vcpkg 是旧代码,我会完全满意,但是,这是新代码。他们只是拥有某种风格是延续的(但usingtypedef不是(?还是为了保存一行代码(public:(?还是有某种间接费用的好处?还是其他一些我根本没有考虑过的事情?

structclass之间的唯一区别是:

  1. 默认成员访问权限(publicprivate(和

  2. 默认继承(如果从类型继承(公共继承与私有继承(。

一旦作者完成向类型添加完public:/private:,1 的最终结果将是相同的。 2 您可以通过在继承时明确控制自己,而不是依赖默认值。这没什么大不了的,也无关紧要。

至于为什么Microsoft在他们的代码中使用struct而不是class,你将不得不问一些Microsoft的人。

关于自由函数与静态函数,我认为类没有任何开销(我根本没有测量过这一点,我只是认为大多数编译器会认识到该类基本上只是函数的命名空间(。事情只是:你不需要上课。

使用仅具有静态函数的类基本上是滥用该类作为命名空间。因此,如果您只是这样做,那么请明确说明并仅使用命名空间。在那里有一个类只会令人困惑,因为你会认为这里可能存在一些状态,当你看到类中的函数是静态的时,只会看到没有。

如果使用得有点错误,这一点尤其重要。想象一下,有人用静态成员函数f实例化一个类A a来调用a.f()。关于性能没有问题,因为构造是无操作的,它几乎等同于A::f().但对于读者来说,似乎涉及某种状态,这令人困惑。

关于另外两个:using优于typedef能够使用模板并且(IMO(更好的可读性。structclass的问题只是关于具有更好默认值的问题,它没有太大区别,但大多数情况下,您想要的是struct所做的事情,因此没有理由使用class

  1. 与 C 兼容(更多(
  2. 避免使用public:关键字公开所有内容,因为例如,所有 COM 对象都只有公共成员函数。