![](/img/trans.png)
[英]In C++, how to return different generic types depending on argument in a class?
[英]C++ Is there a way to initialize a class using different types for the same argument?
我有一个带有零个或两个 arguments 的 class Obj。
我会这样:
class Sphere{
public:
int radius=1;
int a;
};
class Plane{
public:
int a=11;
int b=12;
int c=13;
};
class Light{
public:
int pos=555;
int a;
};
class Obj{
public:
std::string name;
Sphere s;
Light l;
Plane p;
int type;
bool defined;
//with no arguments
Obj(){
defined=false;
type=0;
}
//Type Sphere as second arg
Obj(std::string name,Sphere _s){
defined=true;
type=1;
s=_s;
}
//Or Type Light as second arg
Obj(std::string name,Light _l){
defined=true;
type=2;
l=_l;
}
//Or Type Plane as second arg
Obj(std::string name,Plane _p){
defined=true;
type=3;
p=_p;
}
};
意思应该是能够将多个不同类型的对象放在同一个数组中,只用一种方式输入。
以某种方式可能吗? 任何建议将不胜感激。 谢谢
编辑:
(C++11)
知道它可以编译已经是一个很好的开始。 谢谢。
上述示例仅在 Sphere、Plane、Light 类没有 arguments 时有效。
向 Sphere、Plane、Light 类添加相同的参数编号也会失败。 如果 3 个类有不同数量的 arguments,则相同。
#include <iostream>
class Sphere{
public:
int radius=1;
int a;
Sphere( int _a ){
a=_a;
}
};
class Plane{
public:
int a=11;
int b=12;
int c=13;
Plane( int _a ){
a=_a;
}
//Plane(int _a,int _b,int _c){
// a=_a;b=_b;c=_c;
//}
};
class Light{
public:
int pos=555;
int a;
Light(int _a){
a=_a;
}
};
class Obj{
public:
std::string name;
Sphere s;
Light l;
Plane p;
int type;
bool defined;
//with no arguments
Obj(){
defined=false;
type=0;
}
//Type Sphere as second arg
Obj(std::string _name,Sphere _s){
name=_name;
defined=true;
type=1;
s=_s;
}
//Or Type Light as second arg
Obj(std::string _name,Light _l){
name=_name;
defined=true;
type=2;
l=_l;
}
//Or Type Plane as second arg
Obj(std::string _name,Plane _p){
name = _name;
defined=true;
type=3;
p=_p;
}
};
using namespace std;
int main()
{
int a=111;
int b=222;
int c=333;
Obj sph1=Obj("sphere1",Sphere(a));
Obj sph2=Obj("sphere2",Sphere(b));
Obj lig1=Obj("Light1", Light(c));
Obj lig2=Obj("Light2", Light(c));
//Obj pla1=Obj("Plane1", Plane(a,b,c));
//Obj pla2=Obj("Plane2", Plane(c,b,a));
cout<<"sp1 name:" << sph1.name << endl;
cout<<"sp1 radius:"<< sph1.s.radius << endl;
//cout<<"pla1 name:" << pla1.name << endl;
//cout<<"pla1 p1:" << pla1.p.p1 << endl;
//cout<<"pla2 name:" << pla1.name << endl;
//cout<<"pla2 p1:" << pla1.p.p1 << endl;
cout<<"Hello"<<endl;
return 0;
}
这里是编译器错误:
Error:
vt.cpp: In constructor ‘Obj::Obj()’:
vt.cpp:64:10: error: no matching function for call to ‘Sphere::Sphere()’
Obj(){
^
vt.cpp:22:5: note: candidate: Sphere::Sphere(int)
Sphere( int _a ){
^~~~~~
vt.cpp:22:5: note: candidate expects 1 argument, 0 provided
vt.cpp:18:7: note: candidate: constexpr Sphere::Sphere(const Sphere&)
class Sphere{
^~~~~~
C++17 解决方案是std::variant
,尽管根据defined
,您可能希望将其包装在std::optional
中。
class Obj{
public:
std::string name;
using Value = std::variant<Sphere, Light, Plane>;
std::optional<Value> v;
//with no arguments
Obj() = default;
//Type Sphere as second arg
Obj(std::string name,Sphere _s) : v{std::make_optional<Value>(_s)} { }
// ...
};
std::variant
跟踪为您存储的类型,您不必为所有三个实例的开销付费。 std::optional
为您处理defined
的部分。
通过对构造函数进行模板化并盲目地传递第二个参数,您可能会更聪明一些。
template <typename T>
Obj(std::string name, T _v) : v{std::make_optional<Value>(_v)} { }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.