Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ method declaration question

I have some code in Image.cpp:

Image::Image( int width, int height, int depth ) : m_sFileName(0)  
{  
...  
}  

and in Image.h:  
class Image: public DrawAble, public RenderAble  
{  
...  
private :  
    std::string *m_sFileName;  
};  

My question is: what is happening with m_sFilename in the first line? I guess it is set to NULL but what's the point of doing it that way. Would it be the same to do:

Image::Image( int width, int height, int depth )  
{  
    m_sFileName(0);  
...  
}
like image 588
Jacob Kristensen Avatar asked Dec 14 '22 03:12

Jacob Kristensen


1 Answers

The first uses what's called an initialization list.

When you enter the body of the constructor, all of the classes members must have been constructed (so they can be used). So if you have this:

class Foo
{
public:
    Foo()
    : str() // this is implicit
    {
        str = "String.";
    }
private:
    std::string str;
};

So, str gets constructed, then assigned. Better would have been:

class Foo
{
 public:
    Foo()
    : str("String.")
    {
    }
private:
    std::string str;
};

So that str gets directly constructed. This does not make a difference in your case because pointers have no constructor.

It is generally considered good practice to use an initialization list over running code in the constructor. The initialization list should be used for initializing, the constructor should be used for running code.

Also, why use a pointer to string? If you want a string, use a string; not a pointer to string. Chances are, you actually want a string.


More about initializer lists:

Initializer lists have more uses than just initializing members of the class. They can be used to pass arguments into base constructors:

class Foo
{
public:
    Foo(int i) { /* ... */ }
}

class Bar
    : public Foo
{
public:
    Bar()
    : Foo(2) // pass 2 into Foo's constructor.
             // There is no other way of doing this.
    {
        /* ... */
    }
};

Or constant members:

class Foo
{
public:
    Foo()
    : pi(3.1415f)
    {
        pi = 3.1415f; // will not work, pi is const.
    }
private:
    const float pi;
};

Or references:

class Foo
{
public:
    Foo(int& i)
    : intRef(i) // intRef refers to the i passed into this constructor
    {
        intRef = i; // does *not* set intRef to refer to i!
                    // rather, it sets i as the value of
                    // the int intRef refers to.
    }
private:
    int &intRef;
};
like image 181
GManNickG Avatar answered Dec 28 '22 00:12

GManNickG