简体   繁体   English

C++ 有没有办法为同一参数使用不同类型初始化 class?

[英]C++ Is there a way to initialize a class using different types for the same argument?

I have a class Obj with zero or two arguments.我有一个带有零个或两个 arguments 的 class Obj。

  • No arguments没有 arguments
  • First arg is always a std::string name.第一个 arg 始终是 std::string 名称。
  • Second arg it shoud be of three different class types.第二个参数它应该是三种不同的 class 类型。

I would something like this:我会这样:

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;
    }

};

The meaning should be the ability to put several objects of different types in the same array typed in only one way.意思应该是能够将多个不同类型的对象放在同一个数组中,只用一种方式输入。

Is it possible in some way?以某种方式可能吗? Any suggestion will be appreciated.任何建议将不胜感激。 Thanks谢谢

EDIT:编辑:

(C++11) (C++11)

Knowing that it compiles is already a great start.知道它可以编译已经是一个很好的开始。 Thanks.谢谢。

The above example only works if the Sphere, Plane, Light classes have no arguments.上述示例仅在 Sphere、Plane、Light 类没有 arguments 时有效。

Adding the same argument number to the Sphere, Plane, Light classes also fails.向 Sphere、Plane、Light 类添加相同的参数编号也会失败。 The same if the 3 classes have different number of arguments.如果 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;
}

Here the compiler error:这里是编译器错误:

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{
       ^~~~~~

The C++17 solution for this is std::variant , although based on defined you probably want to wrap it in an std::optional . 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 keeps track of which type is stored for you, and you don't have to pay for the overhead of all three instances. std::variant跟踪为您存储的类型,您不必为所有三个实例的开销付费。 std::optional handles the defined part for you. std::optional为您处理defined的部分。

You could be a bit slicker by templating the constructor and passing the second argument along blindly.通过对构造函数进行模板化并盲目地传递第二个参数,您可能会更聪明一些。

    template <typename T>
    Obj(std::string name, T _v) : v{std::make_optional<Value>(_v)} { }

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

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