如何解决C++ 有没有办法对同一个参数使用不同类型来初始化一个类?
我想要这样的:
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 类具有 没有争论。
向 Sphere、Plane、Light 类添加相同的参数编号也会失败。如果 3 个类具有不同数量的参数,则相同。
#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,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)} { }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。