Legacy UUID Encodings
我知道一种方法是通过在块外定义它,但如果在检查int main() {
if(i = 0) {
myclass1 a = "Example1";
}
else {
myclass2 a = "Example2";
}
cout << a << endl;
}
的条件之前我还没有确定a
是什么类型会怎么样?
答案 0 :(得分:27)
如果您能够使用c++17,则可以使用std::variant
或std::any
,以防您的类型没有公共基类。这些类是任何或指定类型的类型安全容器。 std::variant
的示例如下:
#include <iostream>
#include <string>
#include <variant>
int main() {
bool input = false;
std::cin >> input;
std::variant<int, long, double, std::string> myVariant;
if(input)
myVariant = "Example1";
else
myVariant = 3.14;
std::visit([](auto&& arg) { std::cout << arg << std::endl; }, myVariant);
}
您也可以使用c++17或boost::variant
代替boost::any
。
答案 1 :(得分:20)
C ++是一种静态类型语言,需要在编译时知道代码中使用的变量类型。
没有办法编写一个C ++程序,其中编译了Illuminate\Http\Request::__set_state(array(...))
之类的语句,并且在运行时才知道std::cout << a;
的类型。
为此,您需要一种动态类型语言,例如Python或JavaScript。
答案 2 :(得分:7)
您可以尝试polymorphism。
假设myclass1
和myclass2
“实现”一个名为myclass
的类,您可以执行以下操作:
int main() {
myclass*a;
if (i=0) {
a = new myclass1("Example1");
} else {
a = new myclass2("Example2");
}
cout<<*a<<endl;
}
如果您希望稍后使用myclass1
或myclass2
类型,可以使用dynamic_cast
,但这取决于您的需求以及您在继承的类和您的继承类中实现的行为基类,可能没有必要。
注意我在这里使用原始指针,因为它是一个短暂的对象,很明显程序已经结束。我们建议您阅读smart pointers并正确使用它们以避免memory leaks。注意某些平台中的内存泄漏一直持续到重启后,可能需要手动释放(删除)已分配的内存。更多关于所有here。
答案 3 :(得分:7)
int main() {
auto call = [](auto a) {
std::cout << a << std::endl;
};
if(i = 0)
call(myclass1 { "Example1" });
else
call(myclass2 { "Example2" });
}
答案 4 :(得分:5)
这最终需要多态性,并且可选地,如果你想让它更优雅,factory pattern。工厂模式并不神奇,它只是将if
隐藏在一个漂亮的包装器中。
为什么不采用其他方法,例如std::variant
这基本上是伪装的union
?好吧,如果你能够存储不同类型的东西,甚至任何种类(std::any
)同名,它会很好,但它不是很有用,因为你还希望对该对象做一些有意义的事情。如果你想做完全不同的,无关的事情,那么你也可以拥有if
块作用域的不同对象(以及完全不同的代码)。但是,如果你想在不同的对象上做相同或类似的事情,那么它们(通常)需要是相同或相关的类型。
不同类型通常没有相同的数据成员或相同的可公开访问的成员函数。因此,在具有不同类型的源代码级别上执行相同的操作通常不起作用(除非是巧合)。
但是如果两个类在它们的接口上确实有相同的子集,并且你希望能够以一种或另一种方式互换,那么继承基类是最自然的惯用的事情要做。那就是多态性的发明。使用惯用的东西。
(您可以通过模板助手获得在不同的,不相关的类型上调用具有相同名称的函数的相同净效果,并假设您使用的名称存在,只是工作,但它的风格并不是那么好,而且通过两次实现这个功能会造成巨大的膨胀。)
答案 5 :(得分:4)
我会尝试给你一个实用的答案,假设你已经习惯用JavaScript或其他东西做这种事情而只是试图用C ++编写代码。
首先,你应该在C ++中理解cout << a
。实际上可以根据a
的类型调用完全不同的方法。出于这个原因,当你对这种类型一无所知时,写cout << a
是没有任何意义的。实际上,除非您对C ++的类型有足够的了解以决定要调用哪个方法或运算符,否则您无法对a
执行任何操作。
如果你的两个班级都有一个可接受的共同基础,那么你可以做一些事情:
int main() {
base_class *pa;
my_class1 a1;
my_class2 a2;
if(i = 0) {
a1 = "Example1";
pa = &a1;
}
else {
a2 = "Example2";
pa = &a2;
}
cout << *pa << endl;
}
请注意,当您编写cout << *pa
时,您不必须调用cout << a
将使用的相同方法。在第一种情况下,您正在调用一个知道如何输出base_class
的所有子类的方法,而在第二种情况下,您可能正在调用专门为myclass1
或myclass2
编写的方法。
当没有可接受的基类时,我们就不会在C ++中编写类似的代码:
int main() {
if(i = 0) {
myclass1 a = "Example1";
cout << a << endl;
}
else {
myclass2 a = "Example2";
cout << a << endl;
}
}
请记住,在这些情况下调用的两个方法可以是完全不同的方法。这与调用cout.printClass1(a)
与cout.printClass2(a)
完全相同。 C ++允许您在完全不同的方法中使用相同的名称,因为它可以根据参数类型找出您要调用的方法。
当您编写cout.callWhatever(a)时,JavaScript并没有任何可以在printClass1
和printClass2
之间自动选择的魔法,C ++也不会。在两种语言中,如果您必须为myclass1
与myclass2
调用完全不同的方法,则可以编写不同的调用。
答案 6 :(得分:3)
我自己有这样的代码,当时我实际上尝试了相同代码的不同变体。然后我意识到最好的选择是使用预处理器#if
,它解决了我的问题:
#define VARIATION 2
...
#if VARIATION == 1
myclass1 a = "Example1";
#else
myclass2 a = "Example2";
#endif
我知道它可能无法解决你的问题,但至少它是一种解决方法。
答案 7 :(得分:0)
如果是这个特定问题我会认为这会更容易
int main(){
if(i == 0) //You wrote i=0 !! silly mistake
std::cout << myclass1("Example1");
else
std::cout << myclass2("Example2");
}
或者您可以选择
template<class T>
void foo(T out)
{
std::cout << out;
}
int main()
{
if( i==0 )
foo(myclass1("ex1"));
else
foo(myclass2("ex2"));
}
其他
this 是要走的路 我建议不要在这里使用cout,因为它可能没有重载来接受你的用户定义的类。