繁体   English   中英

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

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

我有一个带有零个或两个 arguments 的 class Obj。

  • 没有 arguments
  • 第一个 arg 始终是 std::string 名称。
  • 第二个参数它应该是三种不同的 class 类型。

我会这样:

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.

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