C++ 基于其他数据成员的类数据成员类型?
假设我有一个基类C++ 基于其他数据成员的类数据成员类型?,c++,class,templates,c++11,C++,Class,Templates,C++11,假设我有一个基类foo和两个派生类a和B。然后我有另一个类bar,它有一个数据成员x,y,z,可以是a,或者,但是类型取决于其他数据成员x_类型,y_类型,以及z_类型,这些值在编译时不可用。我考虑过如何使用模板数据成员并在构造函数中定义类型,在构造函数中我可以得到类型的值,但显然这至少在C++11中是不可能的。那么如何进行呢 class foo{ public: foo(double); int x_type; virtual double do_something(double,
foo
和两个派生类a
和B
。然后我有另一个类bar
,它有一个数据成员x
,y
,z
,可以是a
,或者,但是类型取决于其他数据成员x_类型
,y_类型
,以及z_类型
,这些值在编译时不可用。我考虑过如何使用模板数据成员并在构造函数中定义类型,在构造函数中我可以得到类型的值,但显然这至少在C++11中是不可能的。那么如何进行呢
class foo{
public:
foo(double);
int x_type;
virtual double do_something(double, int) = 0;
};
class A: public foo {
public:
A(double, double);
double do_something(double, int);
private:
double z1;
double z2;
};
class B: public foo {
public:
B(double);
double do_something(double, int);
private:
double w;
};
class bar {
public:
bar();
double do_something2(int);
private:
int x_type;
int y_type;
int x_type;
x; // these are either A or B...
y;
z;
};
在构造器中,我会有
if(x_type == 1){
x = A(arg1, arg2);
} else {
x = B(arg3);
}
在我的实际应用程序中,具有未知类型的派生类和数据成员的数量可能要多得多。我想知道是否有可能使
bar
成为具有多个模板参数的模板类,但我不确定这是否可行,因为参数类型取决于另一个参数?您需要使用多态性并利用公共基类Foo:
private:
int x_type;
int y_type;
int x_type;
std::unique_ptr<Foo> x; // these are either A or B...
std::unique_ptr<Foo> y;
std::unique_ptr<Foo> z;
};
在所谓的“工厂”类或函数中移动创建正确Foo实例的代码是一种很好的做法,以隐藏决策逻辑和构造细节(有时可能非常复杂)。编译时必须知道所有变量的静态类型,因此,它不能基于运行时对象的值进行更改。执行此操作的方法是使
x
、y
和z
都具有类型std::uniqe_ptr
,然后在运行时动态分配A
或B
对象:
class bar {
public:
bar(some_type something) {
if (something == some_value) {
b.x = new A(3.14, 12.34);
} else {
b.x = new B(456.78);
}
}
private:
int x_type;
std::unique_ptr<foo> x;
//...
};
int main() {
bar b(whatever());
}
类栏{
公众:
条形图(有些东西){
如果(某物==某个值){
b、 x=新的A(3.14,12.34);
}否则{
b、 x=新的b(456.78);
}
}
私人:
int x_型;
std::唯一的ptr x;
//...
};
int main(){
b条(无论什么());
}
在这种情况下,还应该将foo::~foo()
声明为虚拟对象,以确保正确销毁派生对象
这通常也是个好主意™ 要完全消除x\u类型
和朋友,并在创建x
后编写与实际类型无关的代码
我想知道是否有可能使bar成为具有多个模板参数的模板类,但我不确定这是否可行,因为参数类型依赖于另一个参数
我不知道这是否有用,但我会把它放在这里以防万一
你看,模板的不同专门化可以从不同的类继承。这样您就可以:
// fwd decl
template <int kind> class bar;
template <> class bar<1> : public A {
public:
bar(double x, double y) : A(x,y) { }
};
template <> class bar<2> : public B {
public:
bar(double a) : B(a) { }
};
我想到了如何使用模板数据成员和在中定义类型
构造函数,我从中获取类型的值,但显然
至少在C++11中是不可能的
C++11附带了一个标准模式,通过使用make.*
template函数创建适当类型的对象,根据一些参数处理模板化构造。请参见例如make\u tuple
函数:
auto t = std::make_tuple(1, "abc", 1.0);
// decltype(t) == std::tuple<int, char const*, double>
template <class T>
struct foo {
T t;
foo(T t): t(t) { }
};
template <class T>
foo<T> make_foo(T t) { return foo<T>(t); }
auto t=std::make_tuple(1,“abc”,1.0);
//decltype(t)==std::tuple
这可以通过创建模板类和模板构造功能来实现:
auto t = std::make_tuple(1, "abc", 1.0);
// decltype(t) == std::tuple<int, char const*, double>
template <class T>
struct foo {
T t;
foo(T t): t(t) { }
};
template <class T>
foo<T> make_foo(T t) { return foo<T>(t); }
模板
结构foo{
T;
foo(T):T(T){}
};
模板
foo make_foo(T){return foo(T);}
如果可以用于x
、y
和z
的所有类型都是从一个公共基类派生出来的,那么带有std::unique_ptr
(+1表示Lyubomir Stankov)的基指针解决方案是一个很好的解决方案
但您询问“是否可以使bar成为具有多个模板参数的模板类”
是的,这是可能的。不是很优雅,但可能
为了好玩,我提出了以下解决方案,但我认为,在更一般的情况下(注意,在我的示例中,a
和B
是不相关的类,而不是从foo
派生的),可能有用(我希望如此)
并定义is
和mis
如下
template <std::size_t ... Is>
using is = indexSeq<Is...>;
template <std::size_t N>
using mis = typename indexSeqHelper<N>::type;
模板
使用is=indexSeq;
模板
使用mis=typename索引seqhelper::type;
通过整数值枚举类型是一件坏事™ 反模式。这可能对应于带有指向多态类foo
的指针的设计。然后应该有一个虚拟析构函数。
template <std::size_t ...>
struct indexSeq
{ };
template <std::size_t N, std::size_t ... Next>
struct indexSeqHelper
{ using type = typename indexSeqHelper<N-1U, N-1U, Next ... >::type; };
template <std::size_t ... Next >
struct indexSeqHelper<0U, Next ... >
{ using type = indexSeq<Next ... >; };
template <std::size_t ... Is>
using is = indexSeq<Is...>;
template <std::size_t N>
using mis = typename indexSeqHelper<N>::type;