Reputation: 3112
Consider the following:
#include <vector>
class Base
{
public:
Base() : x(0) {}
int x;
};
class Derived : public Base
{
public:
Derived(double z0) : Base(), z(z0) {}
double z;
};
class Foo
{
public:
// How to specify a default value for parameter vec0,
// consisting of two Base objects?
Foo(std::vector<Base> vec0 = ? ? ? ) : vec(vec0) {}
std::vector<Base> vec;
};
class Bar
{
public:
// foo1.vec needs to be initialized with two Base objects.
// foo2.vec needs to be initialized with two Derived objects.
Bar() : foo1(? ? ? ), foo2(? ? ? ) {}
Foo foo1;
Foo foo2;
};
int main()
{
Bar bar;
// Code here will want to use Base class pointers to access the elements
// in bar.foo1.vec and bar.foo2.vec.
}
How to specify a default parameter in the Foo constructor?
In the Bar
constructor initializer list, how to specify a vector of Base
objects for foo1
, and a vector of Derived
objects for foo2
?
How to title this question so others needing to solve this problem can find it?
Upvotes: 2
Views: 269
Reputation: 32847
The @sklott 's answer explains well, how the initialization can be done using the initializer list. I would like to focus on the solution in-which Foo
has a vector of pointers to Base
. Using std::vector<std::shared_ptr<Base>>
, you could rewrite @sklott 's solution as follows:
#include <memory> // std::shared_ptr
#include <utility> // std::move
class Foo
{
public:
Foo(std::vector<std::shared_ptr<Base>> vec0 = {
{ std::make_shared<Base>(), std::make_shared<Base>() }
}
)
: vec{ std::move(vec0) }
{}
std::vector<std::shared_ptr<Base>> vec;
};
class Bar
{
public:
Bar()
: foo1{} // calls Foo's default cont'r: initialized with two Base objects.
, foo2{ // initialized with two Derived objects.
{ std::make_shared<Derived>(1.0), std::make_shared<Derived>(1.0) }
}
{}
Foo foo1;
Foo foo2;
};
The above code would have an undefied behaviour, if we do not provide a virtual
destructor to the Base
class. Therefore, to make it complete solution:
class Base
{
public:
Base() : x(0) {}
int x;
virtual ~Base() = default; // don't forget to provide a virtual destructor
};
Upvotes: 2
Reputation: 2859
How to specify a default parameter in the Foo constructor?
Just use initializer list syntax, either explicitly declaring containing elements:
class Foo {
public:
Foo(std::vector<Base> vec0 = {Base(), Base()}) : vec(vec0) {}
std::vector<Base> vec;
};
or implicitly declaring with yet another initializer list:
class Foo {
public:
Foo(std::vector<Base> vec0 = {{}, {}}) : vec(vec0) {}
std::vector<Base> vec;
};
But if your intention is to create by default list with size 2, I think it's better to do so this way:
class Foo {
public:
Foo() : vec(2) {}
std::vector<Base> vec;
};
In the Bar constructor initializer list, how to specify a vector of Base objects for foo1, and a vector of Derived objects for foo2?
You can't do this. You need to either use templates or vector of pointers.
Template example:
template<class V>
class Foo {
public:
Foo(std::vector<V> vec0 = {{}, {}}) : vec(vec0) {}
std::vector<V> vec;
};
class Bar {
public:
// No need to explicitly initialize foo1
Bar() : foo2({{1.},{2.}}) {}
Foo<Base> foo1;
Foo<Derived> foo2;
};
Upvotes: 2