这个问题已在C#/ .Net的背景下提出.
现在我想学习C++中结构和类之间的区别.请讨论技术差异以及在OO设计中选择其中一个的原因.
我将从一个明显的区别开始:
public:or private:,则结构的成员默认是公共的; 默认情况下,类的成员是私有的.我确信在C++规范的模糊角落中还有其他差异.
std::map<int,int> mapy;
++mapy[5];
Run Code Online (Sandbox Code Playgroud)
假设mapy[5]永远是1 是安全的吗?我的意思是,mapy[5]在'++'之前总是会得到默认值0,即使没有显式声明,就像我的代码一样?
以下所有操作均将在GCC 9.1上使用x86-64中的Compiler Explorer在上完成-O3。
我有以下代码:
struct Base {
Base() {}
double foo;
int bar;
};
struct Derived : public Base {
int baz;
};
int main(int argc, char** argv)
{
return sizeof(Derived);
}
Run Code Online (Sandbox Code Playgroud)
16如我所料,它正确地返回的8个字节foo,的4个字节bar和的4个字节baz。这仅是因为Derived继承自Base,因此bar由于Derived是同时包含Base和Derived元素的单一类型而不必填充。
我有两个问题,如下所示:
第一个问题
如果我删除的显式构造函数Base() {},它将开始返回24,而不是16。也就是说,它在bar和之后添加了填充baz。
我无法解释为什么拥有显式默认构造函数与具有隐式默认构造函数有什么不同。
第二个问题
如果然后我更改struct为classfor Base …
假设我有这样的结构:
struct MyStruct
{
uint8_t var0;
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)
这可能会浪费很多(不是很多)空间.这是因为uint32_t变量的必要对齐.
实际上(在对齐结构以便它实际上可以使用uint32_t变量之后)它可能看起来像这样:
struct MyStruct
{
uint8_t var0;
uint8_t unused[3]; //3 bytes of wasted space
uint32_t var1;
uint8_t var2;
uint8_t var3;
uint8_t var4;
};
Run Code Online (Sandbox Code Playgroud)
更有效的结构将是:
struct MyStruct
{
uint8_t var0;
uint8_t var2;
uint8_t var3;
uint8_t var4;
uint32_t var1;
};
Run Code Online (Sandbox Code Playgroud)
现在,问题是:
为什么编译器禁止(按标准)重新排序结构?
如果对结构进行重新排序,我认为你没有任何方法可以用脚射击自己.
不,等等,忍受我...
VLA一直是GCC扩展,但它们被C99采用:
[C99: 6.7.5.2/4]:如果大小不存在,则数组类型是不完整类型.如果大小是*而不是表达式,则数组类型是未指定大小的可变长度数组类型,只能在具有函数原型范围的声明中使用; 尽管如此,这些数组仍然是完整类型.如果size是一个整型常量表达式,并且元素类型具有已知的常量大小, 则数组类型不是可变长度数组类型; 否则,数组类型是可变长度数组类型.
C99也称为ISO/IEC 9899:1999.
现在:
[C++11: 1.1/2]:C++是基于ISO/IEC 9899:1999(以下称为C标准)中规定的C编程语言的通用编程语言.除了C提供的功能之外,C++还提供其他数据类型,类,模板,异常,命名空间,运算符重载,函数名称重载,引用,免费存储管理操作符和其他库设施.
那么C++ 11也不应该有VLA吗?
对于这样的一个小例子,我只想接受Tif Tis astruct/class并拒绝内置类型,如“int”、“char”、“bool”等。
template<typename T>
struct MyStruct
{
T t;
};
Run Code Online (Sandbox Code Playgroud) 在C ++中声明类指针变量时,何时以及为什么我们应该使用'struct'关键字?
我已经在嵌入式环境中看到了这一点,所以我怀疑这是C的一种保留。我已经看到了很多有关在声明struct对象时何时使用'struct'关键字的解释,因为它与C中的名称空间相关(在这里),但是我找不到任何人在谈论为什么在声明类指针变量时可能会使用它。
例如,在CFoo.h中:
class CFoo
{
public:
int doStuff();
};
inline Foo::doStuff()
{
return 7;
}
Run Code Online (Sandbox Code Playgroud)
后来在另一个类中:
void CBar::interesting()
{
struct CFoo *pCFoo;
// Go on to do something interesting with pCFoo...
}
Run Code Online (Sandbox Code Playgroud) 我试图说服一个朋友,这struct只是class现代C++中的一个.经过大量的争论和资源交换(包括一些SO Q&A)后,我想出了一个通过代码证明它的想法,所以我写道:
class A {};
struct B {};
int main()
{
cout << (is_class<A>::value ? "Yes" : "No") << "\n"; // output Yes
cout << (is_class<B>::value ? "Yes" : "No") << "\n"; // output Yes
cout << (is_same<A,B>::value ? "Yes" : "No") << "\n"; // output No ???
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我对第三cout行输出感到惊讶.所以,我现在被困在这里,我不知道我是否正确.
是struct一个class或不?
为什么代码显示两个不同的东西?
更新:
我很清楚struct和class之间有什么区别.令我感到困惑的是答案之间的区别is_class和is_same答案.如果不在这里问我该怎么办?这个网站是为了什么?为什么有些用户倾向于提出问题是没有用的,甚至没有评论来指明它不符合要求政策?
请记住,我们并非所有人都会说流利的英语.并非所有人都有多年的经验.
感谢所有回答或评论的人.
是否总是在 C++ 中class并且struct仅在默认访问说明符上有所不同?或者在某些早期版本中,C++struct更像 C struct?
我从2年左右开始做C++,我说为什么我们需要类中的构造函数而不是结构中的构造函数,以及为什么我们不能在结构中进行构造函数重载...