Solved

Instantiating classes

Posted on 2013-10-31
11
228 Views
Last Modified: 2013-11-01
I come from a C and C# background. I'm told knowing C# isn't much help in learning C++, as the two are very different.

In C# I would define a class, instantiate some instances, and fill in the data for each instance as needed.
Myclass a = new Myclass;

Open in new window

In C++ I see other ways of instantiating a class:
MyClass* a = new MyClass();

Myclass* a = gcnew Myclass();

Myclass a;

class a : MyClass
{
}

Open in new window

The last one seems like I'm creating a new class definition for a class named a, which inherits MyClass, instead of creating an instance of MyClass. Or, since C++ has multiple inheritance and no "implements interface", is the last one better understood as "creating a new class named a which implements the MyClass interface" (I suppose MyClass would then need to be written as an interface, using pure virtual functions.)

When would I want to use class a : Myclass instead of Myclass a?

I'm also unclear on when to use which:
a.data = 1;
a->data = 1;
a::data = 1;

Open in new window

0
Comment
Question by:deleyd
  • 4
  • 3
  • 3
  • +1
11 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 39614370
>>When would I want to use class a : Myclass instead of Myclass a?

These are two completely different things - the first one declares a class 'a' that derives from 'Mayclass' (yet syntactically incorrect, while the second expression
instantiates

Open in new window

an instance of 'Myclass'. Think of it like

class Myclass : public Myparent {

public:

  int data1;
  static int data2;
};

Open in new window


Then (to also address the other part) you'd use that like

Myclass a; // instance
Myclass* b = new Myclass; // dynamically created instance

a.data1 = 1; // regular way to access a public data member of an instance
b->data1 = 2; // access a data member of a pointer to a class
Myclass::data2 = 42; // access a static member of a class;

delete b; // clean up the dynamically created instance of 'Myclass' to avoid memory leaks

Open in new window

0
 
LVL 28

Expert Comment

by:pepr
ID: 39614433
In C# (and Java), the Myclass a; is the definition of the variable named a. The variable is actually a reference to the instance. When not assigned it has null value and you cannot reach any object of that class.

In C++, the Myclass a; means creation of the instance of the Myclass. The instance is named a. It is not a reference, it is the object itself. That a will be deleted automatically -- garbage collector not needed. That kind of a class instance is not created using new (this is not possible in C#).

You can also create an object dynamically in C++ using the new -- similarly to C#. However, the operator returns the address of the newly created object. The address can be stored in a pointer variable. The pointer variable should be of the same type. You can declare the variable like this: Myclass* a; and you can possibly initialize it explicitly by assigning the special nullptr value (for newer C++) or NULL (for older C++ standards).

If a is a reference in C#, it is dereferenced automatically -- it behaves as if the a was the object.

If a is a pointer in C++, you must dereference it explicitely via *a or a-->. This way you can write (*a).data or better a-->data. Notice that the star is somehow common to dereferencing and to the pointer type definition. You can also read the Myclass * a; as *a is of Myclass class (the spaces do not matter, writing the star just after the Myclass is only a convention. When working with pointers in C++ the variables are usually prefixed by p (just another convention).

The C++ language knows also references. The variable of the reference type is defined using & (pronounced as ref), and must be initialized when the variable is created. There is nothing like null reference in C++.

If the data is a static member of the class (kind of global for all instances of Myclass), then you can access it without instantiating the class first. Then you use Myclass::data.

Ask for details.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39614470
In C++ I see other ways of instantiating a class
Since no one has mentioned it, I will make the distinction that gcnew is specific to Microsoft's latest version of C++ (the one that can target .NET). gcnew will give you back a handle to an instance that will be garbage collected for you; whereas, new is for unmanaged types (read not-garbage-collected types).

Read up on gcnew for more info:  http://msdn.microsoft.com/en-us/library/te3ecsc8(v=vs.90).aspx
0
 

Author Comment

by:deleyd
ID: 39615149
I see the class a : Myclass {} is actually creating a subclass of class Myclass.

I'm studying examples of the State Design Pattern. I'm wondering why are all the states subclasses of a base class, instead of different instances of a base class?

I also note we store the subclass in a variable meant to hold (or point to) an instance of the base class. Doesn't this restrict us to treating the stored class as a base class? Then why store a subclass instead?
0
 
LVL 86

Expert Comment

by:jkr
ID: 39615190
>>I'm wondering why are all the states subclasses of a base class, instead of different
>>instances of a base class?

Because inheritance allows you to diversify the functionality of the base class to suit certain purposes. One (heavily used) graphic and self-explanatory example might be the following:

class Vehicle {

  // basic functionality of a vehicle
public:

  void move();
  void stop();
};

class Car: public Vehicle {

  // extends 'Vehicle' by adding Car-specific functionality
};

class Ship: public Vehicle {

  // extends 'Vehicle' by adding Ship-specific functionality
};

class Submarine: public Boat {

  // extends 'Ship' by adding Submarine-specific functionality
public:
  void submerge();
};

Open in new window

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:deleyd
ID: 39615357
But if an instance of Submarine is stored in a variable declared to be a Boat, then you can't call submerge, because the Boat class doesn't know about it.
Submarine s = new Submarine();

Boat b;

b = s;
s.submerge();   //OK
b.submerge();   //doesn't work

Open in new window

0
 
LVL 86

Expert Comment

by:jkr
ID: 39615421
Yes. A boat cannot submerge, whereas a submarine can. That's the whole point behind that concept ;o)
0
 

Author Comment

by:deleyd
ID: 39615523
But in these State Design Pattern examples, we can't do line 7
Submarine s = new Submarine();

Boat b;

b = s;          //save the current state

b.submerge();   //doesn't work because Boats don't submerge

Open in new window

0
 
LVL 28

Accepted Solution

by:
pepr earned 500 total points
ID: 39616089
Yes. But both submarine and boat can float on the surface. In the jkr's example, the Boat should actually be named Ship (line 20). Then you can read:

Submarine is a special kind of Ship (or Boat), where Ship is a special kind of Vehicle (the very base class). This way both submarine and Ship share the common method move. This way, you can s.move() but also b.move() in both cases. This is what is important.

To make one step further, in the example there is only a single way to .move(). The more realistic case is when a car, a ship, a submarine move a bit differently. Then the move() method in the base class Vehicle should be declared as virtual. Then each specialized class can redefine the functionality of the move(). But the miracle is that then even the b.move() would execute the Submarine::move() code.
0
 

Author Comment

by:deleyd
ID: 39617546
Then the move() method in the base class Vehicle should be declared as virtual. Then each specialized class can redefine the functionality of the move().
Ah there's the bit I needed to hear! This is how we change the functionality of move().

I was thinking I would need to somehow encapsulate a function into a variable and then set a storage variable to hold that move() function.

I was thinking I'd have to use C++11 std::bind, in something like this:
#include <functional>
#include <string>
#include <iostream>

class MyState {};

class MyStateA : MyState
{
   public:
      MyStateA(std::function<void()> func)
         : func_(func)
      {
      }

      void execute()
      {
         func_();
      }

   private:
      std::function<void()> func_;
};

struct MyStateB : MyState{};

void changeStateTo(MyState const & /* state */)
{
   std::cout << "changeStateTo" << std::endl;
}

float DoStuff(int)
{
   std::cout << "DoStuff" << std::endl;
   return 0.0f;
}

void foobar(int, std::string, float)
{
   std::cout << "foobar" << std::endl;
}

int main()
{
   MyStateA a1(std::bind(changeStateTo, MyStateB()));
   a1.execute();

   MyStateA a2(std::bind(foobar, 12, "a string", DoStuff(5)));
   a2.execute();
}

Open in new window

This gives me the familiar
MyStateA a1;
MyStateA a2;

Open in new window

pattern I was looking for. But perhaps the class extension is a better way to set the functionality of move()?
0
 
LVL 28

Expert Comment

by:pepr
ID: 39618002
You will find here better C++ experts than me. Anyway, I tend to use C++ in rather simplistic way. Your last example seems to me as the atempt to generalize some finite state machine implementation. I cannot tell you what I think about it without knowing details. My experience is that it is better to stick with simpler solutions as you will have to understand it also four years from now. I can bet you will not believe that it was you who wrote the code, and you will appreciate if it is heavily and effectively commented.

My knowledge related to standard templates is really poor. I do not know details of std::bind. Anyway, I suspect that the foobar, DoStuff and the like have no access to the MyStateA and the like classes. This way I see MyStateXYZ classes existence rather artificial way to invoke a function with arguments. But it is likely I only do not understand your intention.

Back to the original .move(). My comment about making it virtual in the base class was rather simplified. Actually, you can also redefine the non-virtual .move() in the derived classes. But then, the objects will not act polymorphically when referenced via their base class. In C++, you want the method virtual, if you have a container of pointers/references of the base type, and you want to use the pointer/reference to call a method specific to the object of some specialized type. I.e. container stores references to the same base type (homogeneous), but the real objects are specialized and they behave differently when a method the same name is called.

The virtual methods are bread-and-butter of the C++ from very beginning. The class definition uses so called virtual table that points to the method-code related to the specialized/base class .
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now