43

I have been reading a lot of tutorials on C++ class but they miss something that other tutorials include.

Can someone please show me how to write and use a very simple C++ class that uses visibility, methods and a simple constructor and destructor?

bstpierre
  • 30,042
  • 15
  • 70
  • 103
Babiker
  • 18,300
  • 28
  • 78
  • 125
  • 31
    This _has_ to be homework! – xian May 14 '09 at 21:45
  • 7
    I can hardly believe you wasn't able to find any examples via googling on that topic. Most of the examples below, just copy pasted here, from tutorials other the web. – Artem Barger May 14 '09 at 21:52
  • 7
    you seriously must not have looked very hard. – DJ. May 14 '09 at 21:52
  • This should be community wiki, if anything. – Paul Sonier May 14 '09 at 22:01
  • 5
    disagree this is not a wiki question, easy, but not wiki: http://stackoverflow.com/questions/128434/what-are-community-wiki-posts-in-stackoverflow – TStamper May 14 '09 at 22:13
  • 30
    Why not answer this here? This site has crazy Google visibility, this is chance to answer this question for a lot of people. If you don't feel like this question is worth answering just ignore it and move on. – James McMahon May 15 '09 at 21:57
  • What the? So I can post good questions and get down votes, but a question like this doesn't get down votes? Double standards I tell ya – dragonore Jul 23 '15 at 04:56
  • 14
    As a developer coming from other languages, I searched long and hard for intelligible answers to this same problem. I found many partial examples and many that assumed secret knowledge I did not possess. For my purposes, this is a legitimate question and a helpful one. – Craig.Feied May 27 '16 at 02:48

4 Answers4

33

Well documented example taken and explained better from Constructors and Destructors in C++:

#include <iostream>            // for cout and cin

class Cat                      // begin declaration of the class
{
  public:                      // begin public section
    Cat(int initialAge);       // constructor
    Cat(const Cat& copy_from); //copy constructor
    Cat& operator=(const Cat& copy_from); //copy assignment
    ~Cat();                    // destructor

    int GetAge() const;        // accessor function
    void SetAge(int age);      // accessor function
    void Meow();
 private:                      // begin private section
    int itsAge;                // member variable
    char * string;
};

// constructor of Cat,
Cat::Cat(int initialAge)
{
  itsAge = initialAge;
  string = new char[10]();
}

//copy constructor for making a new copy of a Cat
Cat::Cat(const Cat& copy_from) {
   itsAge = copy_from.itsAge;
   string = new char[10]();
   std::copy(copy_from.string+0, copy_from.string+10, string);
}

//copy assignment for assigning a value from one Cat to another
Cat& Cat::operator=(const Cat& copy_from) {
   itsAge = copy_from.itsAge;
   std::copy(copy_from.string+0, copy_from.string+10, string);
}

// destructor, just an example
Cat::~Cat()
{
    delete[] string;
}

// GetAge, Public accessor function
// returns value of itsAge member
int Cat::GetAge() const
{
   return itsAge;
}

// Definition of SetAge, public
// accessor function
 void Cat::SetAge(int age)
{
   // set member variable its age to
   // value passed in by parameter age
   itsAge = age;
}

// definition of Meow method
// returns: void
// parameters: None
// action: Prints "meow" to screen
void Cat::Meow()
{
   cout << "Meow.\n";
}

// create a cat, set its age, have it
// meow, tell us its age, then meow again.
int main()
{
  int Age;
  cout<<"How old is Frisky? ";
  cin>>Age;
  Cat Frisky(Age);
  Frisky.Meow();
  cout << "Frisky is a cat who is " ;
  cout << Frisky.GetAge() << " years old.\n";
  Frisky.Meow();
  Age++;
  Frisky.SetAge(Age);
  cout << "Now Frisky is " ;
  cout << Frisky.GetAge() << " years old.\n";
  return 0;
}
Little Helper
  • 2,419
  • 9
  • 37
  • 67
TStamper
  • 30,098
  • 10
  • 66
  • 73
  • 3
    Hate get/set here. Allows abuse of cat. You should not be able to set the age (as it may be set younger) but you should be able to increment age. – Martin York May 14 '09 at 22:11
  • 5
    Or rather there should be SetBirthday() and then GetAge(). – Reunanen May 14 '09 at 22:15
  • 4
    Also, as this is meant for a learning sample, accessors should be marked constant, as meow since it does not change the contents of the object. – David Rodríguez - dribeas May 14 '09 at 22:59
  • Are the accesor functions like declaring function in a program. – Babiker May 14 '09 at 23:01
  • There's really absolutely no need for a destructor. And iostream.h?!? – user35978 May 15 '09 at 01:29
  • wow...i just come back and see all these comments... I copied and pasted that from some1 else blog for an example...give me a sec 2 come up wit my own..let me take a shower first ;) – TStamper May 15 '09 at 01:55
  • Good job editing -- yours is closest to the best answer right now, IMO, but still has flaws. You never 'new' the string. Also, if you want it to make more sense, you should change it to represent the cat's name. – Nate Parsons May 15 '09 at 04:33
  • Your class will break if copied. – Neil Kirk Mar 29 '15 at 13:15
  • isn't `void SetAge(int age);` a mutator instead of accessor? – Yeo Aug 20 '15 at 16:37
  • Hrm, was the code in the linked post plagiarized from Teach Yourself C++ in 24 hours or was it the other way around? It seems to be almost verbatim... – rschwieb Oct 03 '16 at 19:41
  • What's this? string = new char[10](); ? You define a string, (is this a pet name?), and then don't use it? The source you copied it from does not have this. – HoldOffHunger Jun 30 '18 at 22:11
13

Even if he is a student, worth trying to answer because it is a complex one not that easy at least for a new Visitor of C++ :)

Classes in C++ serve an intersection of two design paradigms,

1) ADT :: which means basically a new type, something like integers 'int' or real numbers 'double' or even a new concept like 'date'. in this case the simple class should look like this,

class NewDataType
{
public:
// public area. visible to the 'user' of the new data type.
.
.
.
private:
// no one can see anything in this area except you.
.
.
.
};

this is the most basic skeleton of an ADT... of course it can be simpler by ignoring the public area! and erasing the access modifiers (public, private) and the whole thing will be private. but that is just nonsense. Because the NewDataType becomes useless! imagine an 'int' that you can just declare but you CAN NOT do anything with it.

Then, you need some useful tools that are basically not required to the existence of the NewDataType, but you use them to let your type look like any 'primitive' type in the language.

the first one is the Constructor. The constructor is needed in many places in the language. look at int and lets try to imitate its behavior.

int x; // default constructor.

int y = 5; // copy constructor from a 'literal' or a 'constant value' in simple wrods.
int z = y; // copy constructor. from anther variable, with or without the sametype.
int n(z); // ALMOST EXACTLY THE SAME AS THE ABOVE ONE, it isredundant for 'primitive' types, but really needed for the NewDataType.

every line of the above lines is a declaration, the variable gets constructed there.

and in the end imagine the above int variables in a function, that function is called 'fun',

int fun()
{
    int y = 5;
    int z = y;
    int m(z);

    return (m + z + y)
    // the magical line.
}

you see the magical line, here you can tell the compiler any thing you want! after you do every thing and your NewDataType is no more useful for the local scope like in the function, you KILL IT. a classical example would be releasing the memory reserved by 'new'!

so our very simple NewDataType becomes,

class NewDataType
{
public:
// public area. visible to the 'user' of the new data type.
    NewDataType()
    { 
        myValue = new int;
        *myValue = 0;
    }

    NewDataType(int newValue)
    {
        myValue = new int;
        *myValue = newValue;
    }

    NewDataType(const NewDataType& newValue){

        myValue = new int;
        *myValue = newValue.(*myValue);
    }
private:
// no one can see anything in this area except you.
    int* myValue;
};

Now this is the very basic skeleton, to start building a useful class you have to provide public functions.

there are A LOT of tiny tools to consider in building a class in C++,

. . . .

2) Object :: which means basically a new type, but the difference is that it belongs to brothers, sisters, ancestors and descendants. look at 'double' and 'int' in C++, the 'int' is a sun of 'double' because every 'int' is a 'double' at least in concept :)

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
10
class A
{
  public:
    // a simple constructor, anyone can see this
    A() {}
  protected:
    // a simple destructor. This class can only be deleted by objects that are derived from this class
    // probably also you will be unable to allocate an instance of this on the stack
    // the destructor is virtual, so this class is OK to be used as a base class
    virtual ~A() {}
  private:
    // a function that cannot be seen by anything outside this class
    void foo() {}
};
1800 INFORMATION
  • 131,367
  • 29
  • 160
  • 239
8
#include <iostream>
#include <string>

class Simple {
public:
  Simple(const std::string& name);
  void greet();
  ~Simple();
private:
  std::string name;
};

Simple::Simple(const std::string& name): name(name) {
  std::cout << "hello " << name << "!" << std::endl;
}

void Simple::greet() {
  std::cout << "hi there " << name << "!" << std::endl;
}

Simple::~Simple() {
  std::cout << "goodbye " << name << "!" << std::endl;
}

int main()
{
  Simple ton("Joe");
  ton.greet();
  return 0;
}

Silly, but, there you are. Note that "visibility" is a misnomer: public and private control accessibility, but even "private" stuff is still "visible" from the outside, just not accessible (it's an error to try and access it).

Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • As a matter of fact, the visibility can cause problems. The compiler picks which overloaded function to call based on visibility and best match in arguments, and can wind up with one that's inaccessible. These concepts can get confusing. – David Thornley May 14 '09 at 21:55
  • Why did Alex use string& name instead of string name – Babiker May 14 '09 at 23:02
  • 2
    "const string& name" means no copy is performed, "string name" tells the compiler to make a copy. Why ask for a copy when you don't need one? It's a good habit to acquire, pass args (that aren't of simple value types such as int, pointer, etc) by const ref when you're using them in a read-only way. – Alex Martelli May 15 '09 at 13:29