views:

198

answers:

3

This is really starting to confuse the hell out of me. When do I use them, when don't I?

For example I was reading a .cpp on linked lists whose class declaration was:

struct CarPart
{
    long PartNumber;
    char Partname[40];
    double UnitPrice;

    CarPart *next;
};

class ListOfParts
{
    int size;

public:
    CarPart *head;

    ListOfParts();
    ~ListOfParts();

    const int count() const;
    void insert( CarPart *item );
    CarPart *retrieve( int pos );
};

With this code, why am I allowed to write

ListOfParts *pPart = new ListOfParts();
CarPart *pCarPart = new CarPart;

Declaring an instance of ListOfParts requires (), but not my CarPart? That's confusing me. When I asked a question before and people told me that such a declaration is a function that returns a ListOfParts object, but not the actual constructor. So I'm guessing this is still something different.

What's happening here?

PS: Am I correct to assume that the const to the right of count() means I cannot modify any values in count?

+9  A: 

Declaring an instance of ListOfParts class does not require () when allocating on the heap. Both forms are valid:

ListOfParts *pPart1 = new ListOfParts();
ListOfParts *pPart2 = new ListOfParts;

EDIT: As the commenters have pointed out, it makes a difference when initialising a POD type (however is's not relevant to your code sample).

However, when declaring a stack variable or a static variable, it matters, because the form with () is the same as declaring a function.

ListOfParts pPart1(); // a function prototype
ListOfParts pPart2; // a object construction

const to the right of count() means you cannot modify any values inside the current object in this function, which will be this->size and this->head (note, you can still change object pointed to by head).

Alex B
So there is nothing different between the two? Nothing at all?
SoulBeaver
@SoulBeaver, nothing whatsoever.
Alex B
There is a difference for POD types -- the version with parentheses will zero-initialize the object.
avakar
It does. Link: http://stackoverflow.com/questions/906734/does-c-do-value-initialization-of-a-pod-typedef
Hans Passant
@avakar, the more you know... I retract my clearly uninformed statement. Long live collective knowledge.
Alex B
+1  A: 

As for your post scriptum: yes, that means when you call count() on a ListOfParts instance, you cannot modify any instance member variables. Except when they are declared mutable.

Pieter
+2  A: 

As it was written you can use both version with and without ():

ListOfParts *pPart = new ListOfParts();

is equivalent to:

ListOfParts *pPart = new ListOfParts;

Shamelessly copied from other answer: Excep POD

The modifier const in declaration means that:

  1. You cannot modify any variable of this class unless it was declared as mutable.

  2. You can call it this method when the object is const.

Try:

#include <iostream>

class test
{
     void testf() {
          std::cout << "void test();" << std::endl;
     }

     void testf() const {
          std::cout << "void test() const;" << std::endl;
     }
 };

 int main() {
      test t;
      t.testf();
      const test &t2 = t;
      t2.testf();
 }
Maciej Piechotka
illegal function-style cast. This might be pretty insightful, but I'm not entirely sure what you're doing. How can you call test itself as a method for an object of test? Furthermore, both are giving me that error I mentioned. Is this normal?
SoulBeaver
Fixed. Sorry - I made a small spelling mistake which I fixed on disk but I haven't 'port' here.
Maciej Piechotka