Question

For a project I am looking at a case where the following situation exists. There is a class foo which requires an identifying number x when constructed. So its constructor argument looks something like foo(x).

Now I want to derive a class based on foo, called bar, which will basically hold two foo's internally and to the outside world acts as a single foo. The way I want to do this is by use of two constructor arguments y and z for bar, which will then, in the constructor, generate foo(y) and foo(z). I hope it's clear.

My current implementation looks something like:

class bar : public foo {
public:
    bar(int y, int z)
    {
        _foo_ptr_1 = foo::foo(y);
        _foo_ptr_2 = foo::foo(z);
    };

private:
    foo *_foo_ptr_1;
    foo *_foo_ptr_2;
};

Where foo is a class that is an already existing class looking something like:

class foo {
public:
    foo(int x) :
    _private_var(x) {
    };
};

Now, I know that since foo has no default constructor with zero arguments this will not work. I would prefer not to add a meaningless constructor with zero arguments to foo for several reasons. Is there a nice way to get this working? Right now my compiler (gcc under Ubuntu) gives me the following error:

error::no matching function for call to foo::foo()

A quick attempt to try and work around this is by replacing the constructor of bar:

bar(int y, int z) : foo(y)

But this also does not work.

I have not been able to find a working solution for this yet online, and would be gratefull for any help.

Was it helpful?

Solution 2

This works just fine for me:

bar(int y, int z) : foo(y)
{
  _foo_ptr_1 = new foo(y);
  _foo_ptr_2 = new foo(z);
}

Please not that trying to invoke a class constructor directly like it was a static method is not how classes are constructed in C++. At the very least, you use new classname(arguments), as above.

This is not really recommended however... explicit memory management using new and delete is easy to get wrong.

First, consider that you may not have to allocate any foo instances at all.. you can just have simple member variables:

class bar : public foo {
public:
  bar(int y, int z) : foo(y), _foo_1(y), _foo_2(z)
  {
  }

private:
  foo _foo_1;
  foo _foo_2;
};

If you really must construct new instances the hard way, you should consider using smart pointers such as unique_ptr.

class bar : public foo {
public:
  bar(int y, int z) : foo(y), _foo_ptr_1(new foo(y)), _foo_ptr_2(new foo(z))
  {
  }

private:
  std::unique_ptr<foo> _foo_ptr_1;
  std::unique_ptr<foo> _foo_ptr_2;
};

unique_ptr ensures that your resources are correctly deallocated when their owner is destroyed. If your _foo member variables don't belong exclusively to their parent bar instance, then you can use shared_ptr instead. It is well worth reading up on the use of these utility classes.

OTHER TIPS

The problem here is that you are trying to work around the inheritance.

By deriving form foo you are saying that a bar is a foo. And a foo has a _private_var, so you have to fill this var with a meaningful value.

If you want to act in the same way as a foo, but not share its implementation, you want to share only an interface with foo. This is done in C++ by using a class with only pure virtual functions and a default constructor. For instance call it foo_interface. This should then be implemented by foo (with a 'real' implementation) and by bar with an implementation to combines the results of two foo's

Also you shoudl instantiate foo* in a different way:

   _foo_ptr_1 = foo::foo(y);

should be

   _foo_ptr_1 = new foo(y); 

or even better, if you can, don't make foo a pointer. As explained here: https://stackoverflow.com/a/23681932/137369

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top