I have written this struct/class tutorial for both C and C++. Differences will be noted where there are any.
Here's the sections that I'm going to do (In no real good order)
Well, there's that. Now down to business...
Section 1: Structs
One very commonly used tool in both C and C++ is the struct. A struct is an arrangement of variables, all encapsulated under one name. Here is an example of a struct:
struct MyStruct
{
int A;
char B[256];
};
This struct is called "MyStruct" and has 2 members. The first one is an int called A, and the second is a char array called B. These are called members of the struct. These members can be accessed externally, so long as the struct is in scope, like so:
int MyFunc()
{
MyStruct var;
var.A = 5;
return var.A;
}
The members of the struct are accessed by putting the defined variable name, followed by a period, then the member name. Other than that, they are like any other variable. This example defines var as being of type MyStruct. This would be fine in C++, but in C you must specify more information when defining it, like so:
int MyFunc()
{
struct MyStruct var;
...
You can include "struct" if you like in C++, but C requires it.
Another type of member is the member function. In C, structs can only have member variables, and classes don't exist. However, in C++, classes and structs can both have member variables and functions. A member function is defined like this:
struct MySecondStruct
{
int SomeFunc();
int a;
...
};
And this function is called similarly to how a member variable is accessed... In code, you could do something like this:
...
MySecondStruct mss;
int ret = mss.SomeFunc();
...
Several more notable things about member functions:
- They are automatically in the namespace of the struct they belong to.
- The actual function declaration must be preceeded by the struct name and two colons. ie. int MySecondStruct::SomeFunc() {...
For instance, when making the function for MySecondStruct called SomeFunc, you would do it like so:
int MySecondStruct::SomeFunc()
{
And you could use the following code inside of it:
a += 5;
return a;
}
Section 2: Classes
Like I mentioned above, classes and structs in C++ are nearly identical tools. However, the difference lies in the default
access specifier. The default access specifier for a struct is
public, but the default for a class is
private. In C++, the terms struct and class are used interchangably.
Again I will say, however, that C has no classes. They are new to C++. And again, in C, structs may only have member variables.
Section 3: Access Specifiers
I will refer to both classes and structs collectively as classes from now on.
There are 3 access specifiers for classes: these are public, private and protected.
public: A public member can be accessed by anything that has the class in scope.
private: A private member can only be accessed by other members, or
friends of the class. Private members cannot be inherited by
derived classes.
protected: A protected member is the same as a private member, but it is inherited by derived classes.
When using an access specifier in a class declaration, you must follow the following form:
class ClassName
{
...
AccessSpecifier:
...
AnotherAccessSpecifier:
...
};
Notice that access specifiers are on their own lines with a colon after them. Take this example:
class MyClass
{
int A; // Private by default for a class
// If this were a struct, it would be public by default
public:
int B; // Public by declaration
... // As is anything else, until another specifier
protected:
int C; // Protected by declaration
};
Now, a member function in this class would have access to all the member variables. However, an outside entity (like, a function in which you're using this class) has access only to "int B;". It cannot access anything else, because everything else is private or protected.
There is a way of overriding the access specifiers of a class for certain instances. You do this by making a function a
friend of the class. This is explained in detail
later.
Section 4: Inheritance: Class Derivation
So far, you've seen how to create classes from scratch. But what if you have a large class, and you want to make another, similar class, with just one or two more functions? There's no reason to totally re-code the entire class, just use class derivation.
When classes are derived, they are defined like this:
class ClassName : BaseClass
{
...
Where BaseClass is replaced by the name of the class you want to inherit from, and ClassName is the name of the new, derived class.
When you inherit from a class, your new class inherits all the public members of the base class as public members. It also inherits all protected members as protected members of the new class. Private members are not inherited, however.
Take the following example:
class FirstClass
{
public:
int A;
private:
int B;
protected:
int C;
};
class NewClass : FirstClass
{
public:
int D;
};
Now, NewClass is inheriting "int A;" as a public member, and "int C;" as a protected member. If you did not use inheritance, and wanted to accomplish the above task, it would look like this:
class NewClass
{
public:
int A;
int D;
protected:
int C;
};
You can also use access specifiers when inheriting classes. Take the following example:
class MegaClass : private NewClass
{
public:
int GetA();
int GetC();
int GetD();
};
This is specifying to inherit all members of "NewClass" as private. You can use public or protected here as well.
Section 5: Friends
Now, let's say that you have a class that's doing some things for you, and your class has public, private, and protected members. It's all working great, and all of the sudden, you realize that a non-member function really really needs access to the classes private members. You really don't want to change your non-member function, because that would make a lot of work.
Never fear! You can make friends of your class and the function that needs the extra access. When you define a function as a friend of a class, it's not actually a member, but still has access to the private members, like as though it was a member. Take this for example:
class BigImportantClass
{
protected:
int k;
... // Lots of important declarations here
public:
friend int GoodExternalFunc(BigImportantClass * lpBIC);
... // Lots more important declarations
};
Notice that a friend function looks just like a member function when defined in the class, except that it has the friend keyword preceeding it. This function would be written like a normal function however, because it is not actually a member of the class, just a friend.
int GoodExternalFunc(BigImportantClass * lpBIC);
{
// Do some good stuff
lpBIC->k = 0;
// Realize that this is a protected member
// But this function is a friend of the
// Class, so it is allowed to do this
return true;
}
That's all there is to friends of classes.
Section 6: Constructors and Destructors
All classes have the option of using two special function types, called Constructors and Destructors. These functions are called automatically by C++. The constructor is called when the class is initialized, and the destructor is called when the class is destroyed.
Constructors and destructors have the same name as the class, but the destructor is preceeded by a tilde (~). Also, to add a twist on this, you can have multiple constructors. All constructors and destructors must be public, and cannot have a return, however.
class SomeClass
{
public:
SomeClass(); // This is the default constructor
~SomeClass(); // This is the destructor
SomeClass(int A); // This is an alternate constructor
... // Other stuff to make the class useful
};
int main()
{
SomeClass a;
// This automatically calls the default constructor
SomeClass b(5);
// This automatically calls the alternate constructor
// with the definition "SomeClass(int A);".
... // Lots of stuff here
} // Now that a and b are going out of scope,
//the destructors are automatically called
Notice that having multiple constructors is simply overloading a function. However, remember to follow the rules for overloading, as well as the constructor rules.
One final word on constructors. If you specify at least one constructor, the compiler will no longer give you a default constructor, and as such you must specify the default constructor as well (if you intend to use it.)
Section A: Review
Now, the following things were covered in this tutorial:
- Creating a struct
- Creating a class
- Adding member variables and member functions to your struct/class
- Deriving one class from another
- Specifying access to members
- Specifying friend functions
- Creating constructors and destructors
And the remember the following points:
- In C++, the terms struct and class can used interchangably
- C++ structs and classes can have member variables and member functions
- C structs may only have member variables, and there are no classes
- In C, when defining something as a struct, you must precede the class name with the keyword struct
- If you specify any constructors, the compiler will no longer provide a default constructor.
Section B: Reference
A good reference for most anything is MSDN online:
http://msdn.microsoft.com/library/default.asp
Also, if you're looking to buy a great book, my favorite is "Programmer's Reference: C/C++" written by Herbert Schildt and published by Osborne Press. (ISBN 0-07-212706-6). You can get it from
Amazon or
Barnes and Noble.
Price: ~$20
Section C: Download Example Source
Download the source code used in the examples here (plus a little extra, to make the program actually work...) It's really simple, but I think a good example of Winsock client/server architecture.
Class Example.cpp |
VarList |
A basic example of a class and several things that can be done with them. I tried to include everything from the lesson in this example. |
A class I wrote for my own use, but is a good example of a use of a class. I designed it to parse query strings and cookies in a CGI program. It parses strings into a variable list. Including functions for navigating this list, it's very useful. Note: It makes use of linked lists, so you need to understand those to understand this class. |
Well, I hope that was helpful for you. If you have any contributions, comments, or corrections -- email me at
jonathan@overholt.org. Thanks, and happy coding!