为什么Microsoft在新代码中使用结构而不是类?
Why is Microsoft using struct rather than class in new code?
所以通常我不会问这样的问题,因为它似乎是基于意见的,或者开始对编码实践进行某种口头战争,但我认为这里可能有一个我不明白的技术原因。
我正在查看 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 是旧代码,我会完全满意,但是,这是新代码。他们只是拥有某种风格是延续的(但using
与typedef
不是(?还是为了保存一行代码(public:
(?还是有某种间接费用的好处?还是其他一些我根本没有考虑过的事情?
struct
和class
之间的唯一区别是:
-
默认成员访问权限(
public
与private
(和 -
默认继承(如果从类型继承(公共继承与私有继承(。
一旦作者完成向类型添加完public:
/private:
,1 的最终结果将是相同的。 2 您可以通过在继承时明确控制自己,而不是依赖默认值。这没什么大不了的,也无关紧要。
至于为什么Microsoft在他们的代码中使用struct
而不是class
,你将不得不问一些Microsoft的人。
关于自由函数与静态函数,我认为类没有任何开销(我根本没有测量过这一点,我只是认为大多数编译器会认识到该类基本上只是函数的命名空间(。事情只是:你不需要上课。
使用仅具有静态函数的类基本上是滥用该类作为命名空间。因此,如果您只是这样做,那么请明确说明并仅使用命名空间。在那里有一个类只会令人困惑,因为你会认为这里可能存在一些状态,当你看到类中的函数是静态的时,只会看到没有。
如果使用得有点错误,这一点尤其重要。想象一下,有人用静态成员函数f
实例化一个类A a
来调用a.f()
。关于性能没有问题,因为构造是无操作的,它几乎等同于A::f()
.但对于读者来说,似乎涉及某种状态,这令人困惑。
关于另外两个:using
优于typedef
能够使用模板并且(IMO(更好的可读性。struct
与class
的问题只是关于具有更好默认值的问题,它没有太大区别,但大多数情况下,您想要的是struct
所做的事情,因此没有理由使用class
。
- 与 C 兼容(更多(
- 避免使用
public:
关键字公开所有内容,因为例如,所有 COM 对象都只有公共成员函数。
- 孤立代码块在结构中引发异常
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- Printf 命令不打印时添加了查找常见除数的新代码
- 为什么Microsoft在新代码中使用结构而不是类?
- 使用哪种模式来执行新代码,只需添加基类的新子类?
- 需要帮助理解这个基本的 Vector3D 结构的代码
- 使用 std::可选标准化,我们可以停止在新代码中使用 nullptr 并弃用它吗?
- 使用C#的结构调用C 代码
- 尽管模板是静态绑定的,但旧代码的对象文件为什么以及如何使用使用通用编程范式的新代码
- 处理动态数据结构时代码中的神秘错误
- VS C++:树状 if/else 结构的代码生成需要很长时间
- 在将 C 结构与 C# 代码联合封送时获取垃圾数据
- 如果程序中没有结构,c++代码运行得更快吗?< / h1 >
- Visual Studio C++在生成后不会更新新代码
- 当asm.js比普通JS代码快的时候,我为什么要用JS写新代码呢?
- 如何在二叉树遍历的末尾添加一行新代码
- 理解数据结构实现代码
- 如何在c++中通过类结构共享代码
- 关于为什么新代码会减慢光线跟踪器的速度的任何想法