Tomaz Fernandes
Tomaz Fernandes

Reputation: 2594

Explicitly initialize member which does not have a default constructor

I´m trying to instantiate an object which has no default constructor so it can be referenced from any methods inside the class. I declared it in my header file, but the compiler says that the constructor for the class creating it must explicitly initialize the member, and I can´t figure out how to do that.

Really appreciate your answers, thank you in advance!

The snippet:

MyClass.h

include "MyOtherClass.h"

class myClass {

    private:
        MyOtherClass myObject;

    public:
        MyClass();
        ~MyClass();
        void myMethod();

}

MyClass.cpp

include "MyClass.h"

MyClass::MyClass() {

   MyOtherClass myObject (60);
   myObject.doSomething();

}

MyClass::myMethod() {

    myObject.doSomething();

}

MyOtherClass.h

class MyOtherClass {

   private:
      int aNumber;

   public:
      MyOtherClass (int someNumber);
      ~MyOtherClass();
      void doSomething();
}

MyOtherClass.cpp

include "MyOtherClass.h"

MyOtherClass::MyOtherClass (int someNumber) {
   aNumber = someNumber;
}

void MyOtherClass::doSomething () {
    std::cout << aNumber;
}

Upvotes: 58

Views: 75762

Answers (4)

6502
6502

Reputation: 114481

There are two errors

  1. Your code MyOtherClass myObject(60); is not initializing the member of the class, but it's instead declaring a local variable named myObject that will hide the member inside the constructor. To initialize a member object that doesn't have a default constructor you should use member initialization lists instead.

  2. You are trying to learn C++ by experimenting with a compiler.

This second error is the most serious error and if not corrected is going to take you to a terribly painful path; the only way to learn C++ is by getting one or two good books and read them cover to cover. Experimenting with C++ doesn't work well for two reasons.

First reason: C++ is complex, changing and sometimes just illogical

First, no matter how smart you are, there's no way you can guess correctly with C++, and in a sense being smart is even dangerous (because you may be tempted to skip over something "you understood already"): the reason is that it happens in quite a few places that the "correct" C++ way is indeed illogical and can only be explained as a consequence of historical evolution of the language.

In other words in many places C++ is the way it is because of its long history of evolution and not because it makes sense, and no matter how smart you are there's no way you can deduce history... history must be studied.

Second reason: UB nasal daemons instead of run-time error angels

The second reason experimenting with C++ doesn't work well is that when you make a mistake quite often the compiler doesn't tell you you are wrong; the code simply compiles; at runtime also you're not told you're wrong, and the code simply does crazy things or may be just works for a while (it's called "Undefined Behavior").

The worst (but common) thing that can happen goes more or less like this:

  1. You write WRONG code, that however compiles fine even without warnings of any kind.

  2. The code also runs fine while you test it (in reality it is not running fine, but the "Undefined Behavior Daemons" just decided to produce the result you're expecting, so seems fine to you).

  3. You go in production (or demo); at that point the UB daemons decided that it would be a funny moment to do things differently, and your (wrong) code makes your house explode this time.

One of the main ideas of C++ is (by default) to not do checks at runtime for logical errors; those checks would be wasted time and programmers make no mistakes (the ones they do are all caught at compile time). This approach is quite questionable (especially the last part is just wishful thinking) but this, liking it or not, is the language.

Upvotes: 6

Russell Greene
Russell Greene

Reputation: 2271

You are almost there. When you create an object in C++, by default it runs the default constructor on all of its objects. You can tell the language which constructor to use by this:

MyClass::MyClass() : myObject(60){

    myObject.doSomething();

}

That way it doesn't try to find the default constructor and calls which one you want.

Upvotes: 46

Chris Drew
Chris Drew

Reputation: 15334

You need to initialize the myObject member in the constructor initialization list:

MyClass::MyClass() : myObject(60) {
   myObject.doSomething();
}

Before you enter the body of the constructor all member variables must be initialized. If you don't specify the member in the constructor initialization list the members will be default constructed. As MyOtherClass does not have a default constructor the compiler gives up.

Note that this line:

MyOtherClass myObject (60);

in your constructor is actually creating a local variable that is shadowing your myObject member variable. That is probably not what you intended. Some compilers allow you turn on warnings for that.

Upvotes: 22

kiviak
kiviak

Reputation: 1103

MyClass::MyClass(): myObject (60){

   myObject.doSomething();

}

Initialization of the data member ends before constructor function body.in the function body you just assign

Upvotes: -1

Related Questions