Joey Roosing
Joey Roosing

Reputation: 2155

instantiation in c++

First of all, I would like to notify you, I have definetly searched for answers about my following question, but im a complete newbie to C++.

I am coming from the luxurious life of C# and Java, now trying to pick up a thing or two about c++

The question is about instantiation.

I use code::block as my IDE of choice.

Currently I am just playing around with what in C# (which I'm actually quite familiar with and have written several applications in) is

2 classes

the class containing main and Person

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


using Models.Person;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
           Person person = new Person();
           Console.WriteLine(person.getName());
        }
    }
}

and the person class:

namespace ConsoleApplication1
{
   public class Person{
       private string name = "Bob";

       public string getName(){
           return name;
       }
   }
}

(dont mind bad or right written syntax, its just to simulate what i want to achieve)

I want to achieve the same in C++

I have looked up, and learned about headers to some extent, and picked up a bit of the syntax. This is what I have right now.

main.cpp

#include <iostream>
using namespace std;

int main()
{
   Person person;
   cout << person->getName() << endl;
}

Person.h

#ifndef PERSON_H
#define PERSON_H

#include <string>

class Person
{
    public:
        Person();
        virtual ~Person();
        std::string getName();
    protected:
    private:
};

#endif // PERSON_H

player.cpp

#include "Person.h"
#include <string>

using std::string;

Person::Person()
{
    //ctor
}

Person::~Person()
{
}

string Person::getName()
{
    return name;
}

Considering the above code, I have multiple questions.

I never found a good source that showed me whether I should instantiate using Person person; or Person person = new Person();

Which one of the two is the one I'm supposed to use?

And another question I'm dying for is, do I define class members in the header file or in the class file?

Currently I'm recieving the following errors:

'person' was not declared in scope and expected ';' before person

I'm not nescesarily asking you to resolve my errors, I'll manage that upon recieving answers on my questions.

Upvotes: 5

Views: 1444

Answers (8)

James Kanze
James Kanze

Reputation: 154047

The main distinction concerning Person is whether you want value semantics or reference semantics---for entity objects, reference semantics are necessary (since they preserve identity), but for most others, value semantics are preferrable. In your example, Person could easily be made to work with value semantics, but in a more realistic case, it would depend on the role of the class in the application.

Anyway, if you define value semantics, you do not (almost never) allocate instances dynamically. You define them as local variables, copying them as needed, and let the compiler take care of the rest. You also make sure that copy, assignment and the destructor do what you want---in modern C++, this is usually the case, as your application level objects will be based on lower level objects with copy constructors, assignment and destruction which do the right thing, but this didn't used to be the case, and it isn't always the case today. If you want entity semantics, you have to decide what the lifetime of the entity should be. (I'd say just as you would in other languages, but many Java and C# programmers forget this. And often get away with it. You won't get away with it, ever, in C++.) Entity objects are normally created using new, and must be destructed when their lifetime ends.

It's also good practice to ban copy and assignment of entity objects (except maybe to provide a clone function) in C++.

Concerning the second point: the complete class definition must be in a single place; you can't reopen the definition once you've closed it with the last curly brace. This means that member function declarations (but not the definitions) and member data must be present in the class definition, in the header file. It's best to put as little as possible in the header file, however, and the definitions of the functions (the implementation) normally belongs in the source file.

(There are exceptions to all of these rules, but they're a good starting point.)

Upvotes: 2

Jon
Jon

Reputation: 437814

As larsmans said, Person person and Person *person = new Person() are result in the new Person instance being allocated in the stack/heap respectively.

What this means for you (and this is the answer to the "which should I use?" question) is that in the first case, the memory for the object is managed automatically (that's the good news). The bad news is that the lifetime of the object is also managed automatically, and you don't have any control over it. As soon as the person variable goes out of scope, the object is destroyed. Period.

In the second case (new), the object's lifetime is managed by you (it will exist until you do delete person). The bad news here is that the memory is also managed by you: if you don't ever do delete person, the memory allocated to that object will leak. It won't make any difference if you have no reference to person anywhere in scope anymore.

So if the lifetime is long enough for you, don't use a pointer. Otherwise, you will have to.

For class members:

  • They have to be declared in the header file; if you don't declare them and try to use them, you will get a compiler error.
  • They may optionally be defined in the header file; if not, you can define them in the .cpp file; if you don't define them anywhere and try to use them, you will get a linker error.

Generally definitions should go to the .cpp file, but it's OK if you define really short methods in the header.

Addendum

Of course there are plenty of details I didn't touch upon in this short answer. Here's a few important ones you might want to look into:

  • Using new/delete to manage memory can also give birth to lots of other problems apart from memory leaks; dangling pointers (which point to memory that has been released, and therefore cannot be used anymore -- this is essentially the "reverse" error than a memory leak) is probably #2 on the list.
  • Using some kind of smart pointer will help in achieving "C# semantics": whenever the last smart pointer to some memory goes out of scope, the memory will be released automatically on the spot (if it points to an object the destructor will run at this time; this is called deterministic destruction, C# does not have it and it has to try to emulate it with IDisposable). There are very good and mature smart pointers you can use in C++0x and Boost.
  • In C++, all types work like C# value types. If a takes up 2MB of memory and you do b = a, you just had the compiler populate a brand new 2MB of memory with a copy of a (and probably do a lot of extra work to achieve that). If that is not your intention, you need to store a pointer or a reference to a instead.

Upvotes: 4

JCooper
JCooper

Reputation: 6535

The errors you're getting come from not using #include "Player.h" (assuming that's what you named the header file containing the declaration for the class Person since that's what your #define PLAYER_H suggests). After that, it'll complain because you're using person->getName() instead of person.getName(). The -> is used with pointers you should probably read up a bit more on this.

As for defining class members, if I understand the terminology correctly, you should declare them in your header file. They are then defined, often implicitly, in the constructor in your class file.

class MyClass {
  int myVar;  // Declare the variable
public:
  MyClass(int inVar);  // Declare the constructor function
};

And then in the class file:

MyClass::MyClass(int inVar)  // Define the constructor function
: myVar(inVar)     // Define the variable
{
}

Of course, you can do both in the header file and it's appropriate to do so sometimes.

class MyClass {
  int myVar;  // Declare the variable
public:
  MyClass(int inVar) // Declare and define the constructor function
  : myVar(inVar)
  {}
};

Upvotes: 1

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361772

The equivalent of your C# code would be this:

#include <iostream>
#include <string>

class Person
{
   std::string name;
   public:
     Person() : name("Bob"){}
     std::string getName() { return name; }   
};

int main()
{
   //automatic variable; doesn't need new!
   Person person;
   std::cout << person.getName() << std::endl;

   //pointer ; need to use new
   Person *pPerson = new Person(); //it allocates memory!
   std::cout << pPerson->getName() << std::endl;
   delete pPerson; //it deallocates the memory!
}

Output:

Bob
Bob

See the online demo : http://ideone.com/cM0uU

Upvotes: 2

Fred Foo
Fred Foo

Reputation: 363817

  1. Person person will construct an object on the stack. Person *person = new Person will construct it in memory on the free store (heap; note the * because you need a pointer). This differs from C#, where you'd choose between struct and class to get either stack or heap allocation. In C++, these keywords have a different meaning. If you choose to allocate on the heap, then you must later delete the object manually.
  2. Implement small, performance-critical methods that are not subject to change in the header. Put everything else in the implementation file.

(Please don't put a using directive at top-level in a header file.)

Upvotes: 2

Tergiver
Tergiver

Reputation: 14517

If you're coming from C#, this explaination might be helpful:

In C++ the declaration/definition of a type doesn't say whether it is a "value type" or a "reference type". The only difference between 'struct' and 'class' is that members are private by default in 'class'. It's how you use it that determines this.

When you declare a Person, you are creating it as a "value type". When you declare a Person*, you are creating a pointer (a reference type in C#) to a Person which normally is allocated on the heap with new. References (i.e. Person&) in C++ are like ref Person in C#.

As James points out in his comment, getting a good C++ book is your best bet.

Upvotes: 1

deek0146
deek0146

Reputation: 994

In java, everything is a reference type, and so has to be instantiated using new, which creates a value type and returns a reference to it. In c++, the basic type is a value type, and a reference type similar to a java one looks like Person* person; You should really drop everything you know from java when going into c++ and start from the basics, it really can be very confusing to go from high to low level programming

Upvotes: 1

karlphillip
karlphillip

Reputation: 93478

In the beginning of main.cpp you must also #include "Person.h".

Upvotes: 1

Related Questions