C++: how to choose the constructor depending on th

2019-03-01 08:41发布

Assume I have a class with different constructors:

class A
{
public:
    A(char* string)
    {
        //...
    }

    A(int value)
    {
        //..
    }

    void check() {}
};

Now I want to create an A object on stack, the constructor must be choosed depending on some condition, but there is a problem: the created object is destroyed then we quit {...} block.

bool isTrue() { /*...*/ }

int main() 
{
    if (isTrue())
    {
        A a("string");
    }
    else
    {
        A a(10);
    }
    a.check(); //error: 'a' is not defined in this scope
}

Suppose I haven't the copy-constructor or operator= in the A class. So how can solve this issue? http://ideone.com/YsjmnK

标签: c++ scope
5条回答
叼着烟拽天下
2楼-- · 2019-03-01 09:25

A a = isTrue() ? A("string") : A(10);

And if a.check() is a const member function, an alternative may be better:

const A& a = isTrue() ? A("string") : A(10);

The object will be destroyed when the reference a go out of scope.

Note since C++17, according to the rule of copy elision the copy/move constructor is not required to be accessible for this case; copy elision is guaranteed here.

And since C++17 you can use std::optional, which doesn't cause any dynamic memory allocation. e.g.

std::optional<A> a;
if (isTrue())
{
    a.emplace("string");
}
else
{
    a.emplace(10);
}
(*a).check();

BTW: A(char* string) is supposed to be A(const char* string).

查看更多
家丑人穷心不美
3楼-- · 2019-03-01 09:33

If the type has a default constructor, you can default-construct an object, immediately destruct it, and then construct it again with the appropriate constructor via placement-new:

A a;
a.~A();
if (isTrue())
{
    new(&a) A("string");
}
else
{
    new(&a) A(10);
}

The C++ standard has several examples similar to the above, just search for .~ and ->~.

Note that this is ultra evil. If your code ever gets reviewed, you are probably going to get fired.

查看更多
Luminary・发光体
4楼-- · 2019-03-01 09:37

You can use the template class:

template<class type> class A
{
protected:
    type    T;
public:

    void A(type t_curr) {T = t_curr;};//e.g.---

    void check() {}
};
查看更多
ゆ 、 Hurt°
5楼-- · 2019-03-01 09:39

You can't satisfy all your stated requirements.

If you can get rid of the requirement for the object to be on stack, you could use a pointer.

A *a;
if (isTrue())
    a = new A("string");
else
    a = new A(10);
a->check();
delete a;
查看更多
对你真心纯属浪费
6楼-- · 2019-03-01 09:41

I had the exact same question a while ago and this is what google helped me find:

unique_ptr<A> foo;

if(isTrue())
    foo = std::unique_ptr<A>(new A("10"));
else
    foo = std::unique_ptr<A>(new A(10));

Its probably too late for the OP but someone else might hopefully find this useful.

查看更多
登录 后发表回答