[英]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
我怎样才能做到这一点?
你可以用指针做这样的事情,只要你的A
和B
类共享一个共同的基础; 像这样:
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。
将“做更多事情”拉入函数中,可能对A
和B
有所不同。
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{}); }
其他替代方法需要为A
和B
找到一个通用类型:
如果他们有共同的基础 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
将根据条件具有类型A
或B
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.