3

I come from a // world and am recently develloping in so please excuse if this is a dumb question.

When I declare a member variable in a class which should be initialized at some point at run time. For example if the member variable wraps functionality of a network device for which the user has to specify the address. After the user entered the address I would create the DeviceWrapper instance. My class would look something like this:

class A
{
public:
  //Method to instantiate dev and other stuff
private:
  DeviceWrapper dev;
}

When declaring the member variable it is my understanding that the default constructor of DeviceWrapper gets called if I don't explicitly call it in the constructor of A. However for the DeviceWrapper class it doesn't make sense to have a default constructor as the class is pointless without knowing the address of the device to wrap.

Am I missing something here or does C++ force me to either define a pointless default constructor in DeviceWrapper or make the class mutable so that the wrapper can receive its address after its creation?

Another alternative would be to make dev a pointer to DeviceWrapper. My idea of using pointers to objects is that the object that owns the instance has the instance directly and every other object that uses it but doesn't own it gets a pointer to the instance. This concept would be broken if I define dev as DeviceWrapper* dev;

So what would be the C++ solution to solve this problem?

mgttlinger
  • 1,435
  • 2
  • 21
  • 35
  • possible duplicate of [Does the default constructor initialize built-in types](http://stackoverflow.com/questions/2417065/does-the-default-constructor-initialize-built-in-types) – Cory Kramer Dec 03 '14 at 14:53
  • 1
    Do you not know the `address` for `dev` at the time you call `A`'s constructor? – Bill Lynch Dec 03 '14 at 14:54
  • @BillLynch no. Lets say `A` is the class containing a GUI where the user enters the address at runtime and then uses the functionality of the wrapped device. – mgttlinger Dec 03 '14 at 14:57
  • @Cyber I have read your linked question. I don't see how my question is a duplicate of that. – mgttlinger Dec 03 '14 at 15:00
  • Then construct the object when you can/need to, or keep trash values for a while. I think you're correct when saying that this scenario requires a pointer (of some kind) or mutability. Declaring something non-existent isn't really a thing. – keyser Dec 03 '14 at 15:01
  • @mgttlinger What you're trying to achieve IS normally done with pointers. If you want class A to have ownership of that pointer, the approach is to use a smart pointer e.g. std::unique_ptr, and hand out the raw pointer to all others that don't own the DeviceWrapper. – nos Dec 03 '14 at 15:12
  • @nos Ok. I just read about `std::unique_ptr` and `std::shared_ptr` and if this is the C++ way I will do that. – mgttlinger Dec 03 '14 at 15:22

2 Answers2

4

The simplest solution is to wrap DeviceWrapper in one of:

std::optional<DeviceWrapper> dev;
std::unique_ptr<DeviceWrapper> dev;
std::shared_ptr<DeviceWrapper> dev;

All three will allow you to initialize DeviceWrapper dev after the construction of A. They all have different copy semantics, and you need to choose which makes sense for your application.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • `std::optional` looks promising coming from a Scala world where `Option` is your bread and butter but is this something that I should use as [cppreference](http://en.cppreference.com/w/cpp/experimental/optional) seems to tell me that this is experimental and will only eventually be included in the standard? – mgttlinger Dec 03 '14 at 15:15
  • @mgttlinger: That's true. There's also `boost::optional` which functions identically and has been around for quite awhile. – Bill Lynch Dec 03 '14 at 15:45
  • It is interesting how the answer to nearly every C++ question I have read here is: "Use this boost library" :D – mgttlinger Dec 03 '14 at 20:13
  • @mgttlinger: That's because there's a close cooperation between the Boost people and the std people. If the need for a function is common enough, it first shows up in boost and then in std. And if it's rarely needed, you're unlikely to see a question here. – MSalters Dec 04 '14 at 08:02
0

There are 2 cases:

  • If you don't have any constructor, then you get a default constructor freely.

  • If you defined any constructor, a not empty one, then you won't get a default constructor freely, so if you need one you'll have to define it.

Therefor, if DeviceWrapper doesn't have any constructor, the default constructor will be called (which is basically does nothing), if it have an empty constructor, it will be called even if you don't have any constructor in A. but if there is some other constructor in DeviceWrapper and there is no empty one, you'll have to initialize it from A constructor.

like this:

A():dev(arguments){}

SHR
  • 7,940
  • 9
  • 38
  • 57
  • 1
    I know that. My question was regarding a case where I do not have a default constructor because there is no useful default value to set the contents of `DeviceWrapper` to but C++ needs a default constructor when I do not explicitly initialize a member variable in the class constructor. – mgttlinger Dec 03 '14 at 15:09
  • The question is if `DeviceWrapper` may stay uninitialized or not. if it is, the empty constructor should bring the object to an uninitialized state. from its name I understand it is only a wrapper to some pointer, or a facet so you just set the pointer to NULL or something like that, and init it later – SHR Dec 03 '14 at 15:15