简体   繁体   中英

What's the best and safest way to dynamically create object of derived class passed as default function argument?

I have a classes

class Base {
public:
    virtual ~Base() {}
    virtual string returnString() = 0;
};

class B : public A {
public:
     string returnString() { return "string"; }
}

class C : public A {
public:
     string returnString() { return ""; }
}

and function

string returnStringFunction(...);

I want to be able to pass object of type C but by default, I want this function to use dynamically created object of type B.

I remember using something like this:

string returnStringFunction(const A& a = *std::make_unique<B>()) 

or

string returnStringFunction(const std::unique_ptr<A> a = std::make_unique<B>()) 

Example function body:

string returnStringFunction(...) {
    return a->returnString();
}

But both of these solutions even though they normally compile and work on my "sandbox" environment, they generate SIGFAULT on workspace. Any idea what's causing it or how to better solve it?

Thanks in advance

As mentioned in comments, const std::unique_ptr<A> a = std::make_unique<B>() should be fine, while the other is not. However, in general default arguments are only second class citizens in C++. If nothing speaks against it I would prefer to overload the function.

If you want the funcion to be callable with and without argument you can provide two overloads:

string returnStringFunction(const Base&);
string returnStringFunction() {
     B b;
     returnStringFunction(b);
}

Not sure why you would dynamically allocate the B here, but if you want you can.

I'd suggest avoiding dynamic memory allocations since there are cheaper ways to do it (unless you have a very strong reason to do it). In this case you can use a const reference:

string returnStringFunction(const A& a = B{}) ...

Obviously, this limits your function to constant methods, but as far as you have described your problem it should work for you.

If your default object is expensive to construct you can use a singleton or similar as default value:

class B : public A {
public:
     string returnString() { return "string"; }

     static B sDefault;
};

// remember to define it somewhere
B B::sDefault;

// ...
string returnStringFunction(const A& a = B::sDefault) ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM