繁体   English   中英

取决于 if 循环的 var 类型

[英]Depending type of var on if loop

假设我想这样做:

type variable; 

if(condition1){
 variable=  something of class A
}
else if(condition2){
 variable = something of class B
}

do more with / variable

我怎样才能做到这一点?

你可以用指针做这样的事情,只要你的AB类共享一个共同的基础; 像这样:

class Base {
    //...
public:
    virtual ~Base() {} // MUST have VIRTUAL member for dynamic_cast
};

class A : public Base {
    //...
public:
    virtual ~A() {}
};

class B : public Base {
    //...
public:
    virtual ~B() {}
};

    // ... 
    bool condition = true;
    Base* variable;
    if (condition)
        variable = new A;
    else
        variable = new B;
    //...

一旦您创建了 class object(并假设这些类至少有一个虚函数),那么您可以在以后的代码中“询问”它实际上使用的是什么类型的dynamic_cast运算符:

    // ... continuing in the same scope as the previous code...
    if (dynamic_cast<A*>(variable) != nullptr) { // Points to an A object:
        // Do something specific to A
    //  A* ptrA = dynamic_cast<A*>(variable);
    //  ptrA->member = value;
    }
    else if (dynamic_cast<B*>(variable) != nullptr) { // Points to a B object:
        // Do something specific to B
    }
    else { // Not an A or a B...
        // (error handling?)
    }
    //...
    // And, of course, don't forget to free the object when finished:
    delete variable;

我怎样才能做到这一点?

您无法在 C++ 或任何其他静态类型语言中实现此目的。 变量的类型不能改变。

几种选择:

在不同的范围内声明一个不同的变量:

if(condition1){
 A variable=  something of class A
 do more with / variable
}
else if(condition2){
 B variable = something of class B
 do more with / variable
}

或者使用一种运行时多态形式,例如标记联合 ( std::variant ) 或 inheritance。

将“做更多事情”拉入函数中,可能对AB有所不同。

void do_more_with(A variable)
{
    // A specific things
}

void do_more_with(B variable)
{
    // B specific things
}

或者

template <typename T>
void do_more_with(T variable)
{
    // things both A and B do
}

或者

void do_more_with(Common variable)
{
    // A and B both convert to Common
}

这些都以相同的方式使用

int main()
{
    if(condition1){
        do_more_with(something_A);
    }
    else if(condition2){
        do_more_with(something_B);
    }

    return 0;
}

这是一种通用的方法,不需要两个类具有共同的基础。

将使用该变量的代码放入通用 lambda 中,然后使用标签调度调用所述 lambda。

template <typename T> struct tag {using type = T;};

// ...

auto lambda = [](auto tag)
{
    using type = typename decltype(tag)::type;
    // Here `type` is either class A or class B.
    type variable = something;
    // Use `variable` here.
};

if (condition1)
    lambda(tag<A>{});
else if (condition2)
    lambda(tag<B>{});
  • 更简单的是创建子 function,可能是模板。

     if (condition1) { do_job(A{}); } else if (condition2){ do_job(B{}); }
  • 其他替代方法需要为AB找到一个通用类型:

    • 如果他们有共同的基础 class,你可能会这样做:

       std::unique_ptr<Base> base; if (condition1) { base = std::make_unique<A>(); } else if (condition2){ base = std::make_unique<B>(); } if (base) { // "limited" to base interface (including dispatch). // free function do_job(*base); // or member (virtual) function base->do_job(); // or visitor pattern base->visit(do_job_visitor{}); }
    • 如果类型不相关,则std::variant是一个不错的选择:

       std::optional<std::variant<A, B>> value; if (condition1) { value = A{}; } else if (condition2){ value = B{}; } if (value) { std::visit([](auto a_or_b){ do_job(a_or_b); }, *value); }

如果条件仅在运行时已知,则这是不可能的。 在静态类型语言中,变量必须只有一种类型,并且不能更改。 为此,您需要一定程度的间接性,例如使用诸如std::variant之类的代数类型或运行时多态性,或者您需要将一些代码抽象到模板中。

如果您确实知道编译时的条件(或者它们可以在编译时计算),那么您可以很容易地做到这一点。

auto var = [] {
  if constexpr (condition1)
    return A{};
  else if constexpr (condition2)
    return B{};
}();

现在var将根据条件具有类型AB

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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