#include <iostream>
// 测试类
class BaseA
{
public:
void print(int v){ std::cout << __FUNCTION__ << " value : " << v << std::endl; }
};
class BaseB
{
public:
void print(const std::string_view str){ std::cout << __FUNCTION__ << " value : " << str << std::endl; }
};
class BaseC
{
public:
BaseC(int a = 1, double d = 1.1, std::string str = "")
{
std::cout << "a: " << a << " d: " << d << " str: " << str << std::endl;
}
~BaseC() {}
public:
void print(double d) { std::cout << __FUNCTION__ << " value : " << d << std::endl; }
};
/************************************************VariableTypeClass_A 可变数量类继承模板***********************************************************/
// 未提供构造函数 通过模板实例化或{}进行构造对象
template<typename... Args>
class VariableTypeClass_A: public Args...
{
public:
// 如果继承了Args类,并且类中的函数print是重载关系。
// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
using Args::print...;
};
// 未提供构造函数 类外提供推倒方式 进行声明,达到根据参数个数,确定类型个数并实例化类。
template<typename... Args>
class VariableTypeClass_B : public Args...
{
public:
// 如果继承了Args类,并且类中的函数print是重载关系。
// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
using Args::print...;
};
template<typename...Args>
VariableTypeClass_B(Args...)->VariableTypeClass_B<Args...>;
// 提供构造函数
template<typename... Args>
class VariableTypeClass_C : public Args...
{
public:
// 通过 {}... 或 ()... 推断类型实例化基类
VariableTypeClass_C(const Args&... args) : Args{ args }... {}
//VariableTypeClass_C(const Args&... args) : Args(args)...{}
public:
// 如果继承了Args类,并且类中的函数print是重载关系。
// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
using Args::print...;
};
// 为继承的每个类,提供不同参数的构造函数(可变参数构造函数). 需要类外提供推倒方式 进行声明
template<typename... Args>
class VariableTypeClass_D : public Args...
{
public:
template<typename... Ts>
VariableTypeClass_D(Ts&&... args) : Args( std::forward<Ts>(args))...{}
public:
// 如果继承了Args类,并且类中的函数print是重载关系。
// 需要通过using进行声明. 如果继承的基类中函数相同,并且都用了using声明,则会报歧义错。
using Args::print...;
};
template <class ...Args>
VariableTypeClass_D(Args&&...)->VariableTypeClass_D<std::remove_reference_t<Args>...>;
/// test function
void test_VariableTypeClass_A();
void test_VariableTypeClass_B();
void test_VariableTypeClass_C();
void test_VariableTypeClass_D();
/*************
* 总结: 如果在实例化类对象时,不通过<>显示对象实例化。通过参数隐式类型推导要继承的类型。
* ① 必须在类中提供非模板 构造函数如 test_VariableTypeClass_C
* ② 在实例化对象时通过{}方式进行实例化如 test_VariableTypeClass_A
* ③ 在类外 提供可变参数声明 template<typename...Args> VariableTypeClass_B(Args...)->VariableTypeClass_B<Args...>; 如 test_VariableTypeClass_B
* 注意: 如果构造函数为模板构造函数,同样需要提供 可变参推倒声明。如 test_VariableTypeClass_D
* 仅适用通过参数推导类型。因为提供了拷贝构造方式构造基类,所以要有对象。
************/
/// 附 继承一种类型,但该类型的参数可变
// 继承类可变参构造(针对不同类的构造函数不同)
template<typename T>
class VariableConstructor_A : public T
{
public:
template<typename... Args>
VariableConstructor_A(Args... args):T(args...) {}
};
template<typename T>
class VariableConstructor_B : public T
{
public:
template<typename... Args>
VariableConstructor_B(Args&&... args) :T(std::forward<Args>(args)...) {}
public:
using T::print;
};
void test_VariableConstructor()
{
VariableConstructor_B<BaseC> c(1,1.1,"ssss");
c.print(1.1);
}
int main()
{
//test_VariableTypeClass_A();
//test_VariableTypeClass_B();
//test_VariableTypeClass_C();
//test_VariableTypeClass_D();
test_VariableConstructor();
return 0;
}
void test_VariableTypeClass_D()
{
BaseA a;
BaseB b;
VariableTypeClass_D vatd_1(a,b);
vatd_1.print("VariableTypeClass_D");
}
void test_VariableTypeClass_C()
{
BaseA a;
BaseB b;
VariableTypeClass_C vatc_1(a,b);
vatc_1.print("VariableTypeClass_C");
}
void test_VariableTypeClass_B()
{
BaseA a;
BaseB b;
VariableTypeClass_B vtb_1(a,b);
vtb_1.print("类外提供推到方式..");
}
void test_VariableTypeClass_A()
{
// 使用方式 1 通过模板<>实例化
VariableTypeClass_A<BaseA, BaseB> vta_1;
vta_1.print("hello world.");
// 使用方式 2 如果VariableTypeClass_A类中没有提供构造函数,通过 {基类对象A,基类对象B...} 方式进行类型推断构造
BaseA a;
BaseB b;
VariableTypeClass_A vta_2{ a,b };
vta_2.print("2");
}
C++ 17/20/23可变参数模板类继承使用示例(低于c++17可参考)
最新推荐文章于 2023-02-07 16:06:37 发布