How to use class?

Like the how to use void I am wandering how to use class I know struct but class is a mystery

That’s a really big question depending on how deep you want to go.

Superficially the only difference between class and struct in C++ is that class defaults to private access while struct defaults to public access as per C++'s access specifiers.

But if you mean how to use them to full effect as in the whole object-oriented, member function using, inheritance using stuff, then that’s going to take more than just a one page comment to explain.

Basically you’d have to read many tutorials, try a lot of experiments to get a grip on how it all works, and then practise and eventually move on to bigger, more complicated things.

I suggest focusing on member functions and access specifiers first since they’re easy enough to get a grip on.

Inheritance on the other hand is a big thing because it’s part of the object orientation paradigm, which is a way of thinking about code.
At that point you’d have to actually learn about the object oriented paradigm itself, which involves a significant shift in thinking.

Learning a new paradigm is probably the closest thing the programming world has to a spiritual journey.

can you give me a example?

An example of what?
An example of an online tutorial?
An example of member functions?
An example of access specifiers?
An example of inheritance?

an example of using class or can u not do that simply. is it like a big thing?

I could give an example of some of the features of classes, but even if I show you examples of all the features, without reading about them it won’t do you much good. It’s not something you can understand just by seeing, there’s theory behind it that has to be understood before everything makes sense.

I’ve written some basic examples, but really you’d be better off reading some proper tutorials:


At the simplest level, to demonstrate the difference between struct and class using only member variables and access specifiers, these two things are equivalent:

struct Point
{
  int X;
  int Y;
};
class Point
{
public:
  int X;
  int Y;
};

And so are these:

struct Point
{
private:
  int X;
  int Y;
};
class Point
{
  int X;
  int Y;
};

As a demonstration of access specifiers, there’s this:

class AcessDemo
{
public:
  int PublicValue;
private:
  int PrivateValue;
};

void SomeFunction(void)
{
  AccessDemo demo;
  demo.PublicValue = 5; // Ok
  demo.PrivateValue = 10; // Compile error
}

The main reason you might want to make PrivateValue private is because of a concept called information hiding.

In basic terms you want to keep certain variables private either to prevent them being modified by code that shouldn’t be modifying them or to hide how a bit of code is implemented in case the implementation has to be changed (e.g. the code breaks, or the code is changed to be more efficient).
This is something that is easier to appreciate when you’ve encountered the kind of problems it sets out to prevent.


A simple demonstration of member functions:

class Health
{
private:
  float value;
public:
  float getValue(void)
  {
    return this->health;
  }
  void heal(float amount)
  {
    this->health += amount;
  }
  void damage(float amount)
  {
    this->health -= amount;
  }
};

void someFunction(void)
{
  Health healthA;
  healthA.heal(1000); // health.value is now 1000
  healthA.damage(100); // health.value is now 900
  Health healthB;
  healthB.heal(500); // health.value is now 500
  healthB.damage(10.5); // health.value is now 489.5
}

Member functions follow the principles of encapsulation in which an object’s state is modified by operations being performed on it. These operations are bundled with the class rather than being separate entities.


A simple demonstration of constructors and destructors:

class Memory
{
private:
  char * data;
  size_t size;
public:
  Memory(size_t size)
  {
    this->size = size;
    this->data = (char*)malloc(size);
  }
  ~Memory(void)
  {
    this->size = 0;
    free(this->data);
  }
  size_t getSize(void) { return this->size; }
  char getChar(size_t index)
  {
    // Boundry checking to prevent buffer overflow
    if(index < 0 || index >= size) return '\0';
    return data[index];
  }
  bool setChar(size_t index, char value)
  {
    // Boundry checking to prevent buffer overflow
    if(index < 0 || index >= size) return false;
    data[index] = value;
    return true;
  }
};

void someFunction(void)
{
  Memory memory = Memory(256); // Constructor is called, allocate 256 bytes
  auto size = memory.getSize(); // Gets size, which is 256
  memory.setChar(0, `a`); // Puts an 'a' at position 0
  auto c = memory.getChar(0); // Gets the 'a' at position 0
} // End of function, memory falls out of scope, destructor is called

Constructors and destructors are a very useful feature, many languages have constructors, but few have destructors.
Constructors ensure that an object is properly initialised to a valid value whilst destructors make sure proper cleanup operations are performed: freeing memory, closing files, closing sockets.
These underly C++'s RAII principle (Resource Acquisition Is Initilisation).


Inheritance is something that’s quite difficult to demonstrate.
Many demonstrations resort to contrived “mammal inherits animal” or “circle inherits shape” examples.
Instead I’m going to try to give a more ‘real world’ example, but it’s not a particularly kind example. For this demo, assume the Memory class from the earlier example is also available.

class TextWriter
{
  virtual ~TextWriter(void) {}
  virtual size_t write(const char * text) = 0;
};

class MemoryWriter : public TextWriter
{
private:
  Memory * memory;
  size_t index;
public:
  MemoryWriter(Memory * memory)
  {
    this->memory = memory;
    this->index = 0;
  }
  size_t write(const char * text) override
  {
    size_t charsWritten = 0;
    while((*text != '\0') && (this->index < this->memory->getSize()))
    {
      this->memory->setChar(this->index, *text);
      ++text;
      ++this->index;
      ++charsWritten;
    }
    return charsWritten;
  }
};

class FileWriter : public TextWriter
{
private:
  FILE * file;
public:
  FileWriter(const char * filename, const char * mode)
  {
    this->file = fopen(filename, mode);
  }
  ~FileWriter(void)
  {
    fclose(this->file);
  }
  size_t write(const char * text) override
  {
    return fwrite(text, 1, strlen(text), this->file);
  }
};

void writeSomething(TextWriter * writer)
{
  writer->write("Something");
}

void someFunction(void)
{
  Memory memory = Memory(500);
  MemoryWriter mWriter = MemoryWriter(&memory);
  FileWriter fWriter = FileWriter("file.txt", "w");
  writeSomething(&mWriter);
  writeSomething(&fWriter);
}

Here the TextWriter class is an abstract class (i.e. it has no implementation, it’s just an interface). It has a virtual destructor, which you need not worry about, and a virtual function called write that attempts to write a string and returns the number of characters that were written.
The MemoryWriter uses our earlier Memory class as its backing store and writes the string to Memory.
The FileWriter class opens a file and writes the string to the file it has opened, making sure to close the file when it’s destroyed.

This code is actually simplified for demonstration purposes, to make it properly functional and well designed would require explaining other things that are even further advanced.

For now, this is the crux of inheritance:

The TextWriter class is what’s called the ‘parent’ class or (in Java parlance) the ‘superclass’.
It represents some kind of interface that performs a certain job.
In this case its job is to write text.
What it writes the text to is unspecified because it’s unimportant.
The point is that it’s an agreed upon interface for writing text.

The FileWriter and MemoryWriter are ‘child’ classes or (in Java parlance) the ‘subclasses’.
They are responsible for filling in the blanks - they provide the implementation for the TextWriter's interface.
They are what decides where the text gets written to.
One writes to a file on a hard drive or usb stick or something, the other writes to a block of memory in RAM.
But the important thing is that they both adhere to the rules of TextWriter: they accept a string, they ‘write’ that string (whatever that means to them), and they return how many characters they have written.

This one of the main things define inheritance.

There’s much more too it than that, there’s also how member variables and member functions get inherited, there’s how the child classes can be treated as if they were their parent.
It’s a deep topic and one pretty much nobody on the planet could summarise in less than several pages.


So all in all, there’s your drop in the ocean.

The truth of the matter is there’s no simple answer to ‘what is a class’ or ‘how do I use a class’.
It’s so closely tied to object orientation that beyond just using the simple parts like member functions, it’s something that requires lots of tutorials and lots of reading.

It’s a big thing to understand and it takes work getting there, but it’s totally worth it.
It turns your view of programming upside down and it will almost certainly make you a better programmer in the process.

There’s no rush to learn it all at once though, the journey of a thousand miles begins with but a single step.

Just make sure to read and practice every day and eventually you’ll hit a point of understanding where you can start looking at your old code and finding ways to make it better, ways to give it a more object-oriented approach.

5 Likes