34

I have a class that looks like:

class Foo
{
public:
    Foo();
    virtual ~Foo();

private:
    Odp* bar;
};

I wish to initialize bar to NULL. Is this the best way to do it?

Foo::Foo() : bar(NULL)
{
}

Also, is it necessary that the destructor is virtual? (If that is true, then must the constructor be virtual as well?)

luke
  • 36,103
  • 8
  • 58
  • 81
Nick Heiner
  • 119,074
  • 188
  • 476
  • 699
  • 1
    Arguably better is just `Foo::Foo() : bar() {}` (Note, no `NULL`.) Best is to not have the pointer, though. – GManNickG Jul 07 '10 at 18:04
  • 2
    Why is that better? Is the `NULL` implicit? – Nick Heiner Jul 07 '10 at 21:41
  • 2
    "Why is that better?" You don't need to include a header file for the definition of `NULL` (which is just `0` anyway). "Is the `NULL` implicit?" Yes. `bar()` is a value-initialisation; in the case of a pointer, it initialises it to null. – Mike Seymour Jul 07 '10 at 23:59
  • Slightly fewer cases actually, you only need it to be virtual if: - somebody inherits from your class - somebody else uses a pointer to your class to delete that object And even then it would only cause problems if that derived class had a non-trivial destructor. Because that last one is very hard to determine the general idea is that if somebody derives from you, you should use a virtual destructor. Derives in this context is the Java "extends", not "implements". – dascandy Oct 21 '10 at 05:53

7 Answers7

39

I wish to initialize bar to NULL. Is this the best way to do it?

It is the correct way. So, yes.

Also, is it necessary that the destructor is virtual?

No. The destructor only needs to be virtual if you will be inheriting from the Foo class and will be using a Foo pointer to delete those derived classes (although as a general rule of thumb, it should be virtual if there are any other virtual members).

(If that is true, then must the constructor be virtual as well?)

No. Constructors neither need to be virtual, nor can they.

greyfade
  • 24,948
  • 7
  • 64
  • 80
  • +1 Good concise answer. I initialize non-constant members in the ctor's body. It makes reading the code a bit more clear (in regard to the type of the member qualifier). – Poni Jul 07 '10 at 18:11
  • 16
    @Poni: No you don't, you reassign them. All members are initialized by the beginning of the constructor body. This is why it's generally seen as bad practice to "initialize" things there. Sure, with primitive types you lose nothing, but not all types are primitive, and it's best to be consistent. "Clear" will come as you use them more and get used to the syntax. – GManNickG Jul 07 '10 at 18:17
  • MyClass::MyClass() : m_const_var(VALUE) { this->m_non_const_var = OTHER_VALUE } <<<< didn't exactly get what you said GMan but this is what I meant to. So, you're saying this way is wrong? You're saying that we should include m_non_const_var's initialization in the ctor's members' initialization area just like the doing with m_const_var? – Poni Jul 07 '10 at 18:36
  • 3
    @Poni: I got that's what you said, I'm trying to point out that `m_non_const_var` should have been initialized in the initialization list. When you say `= OTHER_VALUE`, you are assigning, not initializing. Initialization list is for initializing. :) Your code would make me wonder if you were just being inconsistent or if there was some reason those couldn't be initialized. The constructor body should be where you run any code required to initialize your *class*, not the members. – GManNickG Jul 07 '10 at 18:43
  • 1
    The destructor only needs to be virtual if you want polymorphic deletion through a pointer to the base, otherwise make it protected and nonvirtual. See e.g. [Virtuality](http://www.gotw.ca/publications/mill18.htm). – Georg Fritzsche Oct 21 '10 at 06:07
10
  1. Yes, the initializer list is best.

  2. Maybe. The destructor should be virtual if you intend to have any other virtual functions in the class, or if you intend the class to be inherited from (although usually those things go together).

  3. No. It's not possible to have a virtual constructor in C++. (what would such a thing even mean?)

The nature of your question suggests to me that you don't really understand what the virtual keyword does, or what is is for, and you are just copying something you saw elsewhere or in a tutorial. It's best to understand the purpose of all of the code you're writing. Here might be a place to start: http://www.parashift.com/c++-faq-lite/virtual-functions.html

Tyler McHenry
  • 74,820
  • 18
  • 121
  • 166
  • Just an FYI in response to "what would such a thing even mean?": some people might use the term "virtual constructor" for the factory pattern (http://www2.research.att.com/~bs/bs_faq2.html#virtual-ctor). – Michael Burr Jul 07 '10 at 21:16
9

Four distinct ways exist. Which one is the best is up to you

Foo::Foo() : bar() // value initialization
{
}

Foo::Foo() : bar(0) // direct null pointer constant
{
}

Foo::Foo() : bar(NULL) // null pointer constant by macro
{
}

Foo::Foo() : bar(nullptr) // pointer literal of type std::nullptr_t
{
}
nurettin
  • 11,090
  • 5
  • 65
  • 85
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
4
  1. Yes
  2. Regarding your second question about destructor being virtual see: http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7 Short answer, No destructor isn't necessary to be vitual in your case.
  3. There are no such things as virtual constructors.
bits
  • 8,110
  • 8
  • 46
  • 55
3

Another option you might want to consider is to use a smart pointer class (such as boost::scoped_ptr, boost::shared_ptr or C++0x's unique_ptr) instead of a raw pointer. The constructor of the smart pointer will make sure it's initialized to something NULL-like if you don't need some other explicit initialization. The smart pointer will also ensure that the pointed-to object is destroyed.

You just need to decide what kind of smart point policy is appropriate for the item and choose accordingly (even auto_ptr might be better than a raw pointer as long as you're aware of the various pitfalls).

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
2

1, yes

2, only if you want somebody to be able to derive from your class and use a pointer to the base class - but make the dtor virtual anyway

3, no you can't have a virtual ctor (or all ctors are virtual I suppose?)

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • 4
    "all ctors are virtual" - no, the decision on which constructor to call is made at compile time. "Virtual" would imply a run-time decision. – Mike Seymour Jul 07 '10 at 17:59
0

Virtual functions are to determine which function of class (which is defined in both base and derived class) must be called during run time. But when object is created compiler knows which constructor is to be called. for eg. when base object is created base constructor is calledand same for the derived class. Hence making constructor to be virtual doesnt makes any sense.But once when the base class object pointer points to the derived class object, and then destructor is called ,compiler gets confused which destructor(either of baseor derived) needs to be called, which is can only resolved using lookup table vtable and hence destructor needs to be virtual.

Priji
  • 1