I never got the point of structs. I mean, it's literally just like a class, except it can't do anything.
It's exactly like a class. When you say, "it can't do anything", what particularly can structs not do? it can do everything a class can do (constructors, destructors, operators, functions, inheritance, etc...). It's exactly the same thing - two different keywords for identical purposes.
(Note: because C++ likes to repurpose keywords for unrelated purposes, 'class' is also an unrelated keyword for template arguments, and is interchangeable with 'typename' - but that's unrelated to the regular usage of the 'class' keyword)
'C' had 'struct'. C++ wanted the idea of object-orientedness, and added the 'class' keyword for basically no purpose except to underline the OOP-ness. It could've just as easily kept using the 'struct' keyword and C++ would be 100% the same, or could've easily gotten rid of the 'struct' keyword and only used 'class' for everything. The only reason it didn't get rid of the 'struct' keyword was for backwards compatability, and the only reason they added the 'class' keyword was... to be hip?
I'm trying to underline that they are the same and so am being slightly facetious, but you can read Bjarne's own reasoning (at least somewhat). Essentially, though, it's just a quirk in C++'s design that there are two separate keywords.
Here's some example code showing that they have the same features:
#include <iostream>
struct MyStructBase
{
int var = 0;
//Structs can have member functions.
void MemberFunction()
{
std::cout << "var = " << var << std::endl;
}
//Structs can have virtual functions (even pure virtual).
virtual void SetSomething(int x) = 0;
};
//Classes can inherit from structs (because structs are classes - they're the same).
class InheritsFromStruct : public MyStructBase
{
public:
void SetSomething(int x) override { this->var = x; }
};
//Structs can inherit from classes (because classes are structs - they're the same)
struct InheritsFromClass : public InheritsFromStruct
{
//Structs can have constructors and destructors.
InheritsFromClass(int value)
{
//Structs can do polymorphism just like classes (because it's two keywords for same feature)
InheritsFromStruct &polymorphism = *this;
polymorphism.SetSomething(value);
}
//...stuff...
};
int main()
{
InheritsFromClass myStruct(357);
myStruct.MemberFunction();
return 0;
}
What's the point of that? What can it be used for?
Well, since structs and classes are exactly the same (except for the aforementioned defaulting to public vs private, and the default access for structs/classes you inherit from - which is arguably an inconsequential and unnecessary difference), they can be used for exactly the same purposes. Two reserved keywords for the exact same functionality.
So, since they are the same thing, C++ programmers have generally decided to give them conceptual differences: structs for collections of data without logic, and classes for logic bundled with data, or just logic (or just interfaces without logic, or etc...). It's a "how we code" difference, rather than a difference in C++ code.
When you want an integer, do you do "int" or "signed int"? They both mean the same. You can also say, "signed long int", "long int", or just "long".
When you want an unsigned integer, do you do "unsigned" or "unsigned int"? They both mean the same.
(alright, so on some architectures "int" and "long int" may be different sizes, but on many systems they'd be the same)
Different people come up with their own coding styles and guidelines, and the C++ community in general has come to some consensus on some of it.
For bonus points:
auto signed long int myInt; //Usage of 'auto' prior to C++11. This usage of auto has now been either removed or deprecated.
Alot of older C++ features are so underused, some of them could be removed. Personally, I never liked the whole signed/unsigned/long system, and think C++ should standardize around the int32_t and friends, though I use 'int' and 'unsigned' when I don't care about the size.