班级Derived
是班级Base
的孩子。您无法修改班级Base
。为Derived
定义构造函数和赋值运算符,以便可以从以下实例构造它:
Base
1
Derived
1
N
非多态且不相关的类型Foo1
,...,FooN
2 。
1 使用Base
复制构造函数完成Derived
和Base
的构建。
2 所有Foo1
,...,FooN
的构建都是通用算法完成的。
N+1
单独的构造函数+ N+1
单独的赋值运算符。绝对不优雅。大量无用的代码:N+1
方法声明在源头中的头+ + N+1
方法实现中。未使用模板的强大功能。
声明并定义常规拷贝构造函数
Derived::Derived ( const Base& object_reference ) { ... }
声明模板构造函数:
template<typename type>
Derived::Derived ( const type& object_reference );
为Foo0
,...,FooN
template<>
Derived::Derived<Foo0> ( const Foo0& object_reference ) { ... }
...
template<>
Derived::Derived<Foo9> ( const Foo9& object_reference ) { ... }
因此,标头只包含两个构造函数,只包含两个赋值运算符。但是我们必须在源代码中实现N+1
方法。我相信无论如何都有更好的解决方案。
template<typename type>
Derived::Derived ( const type& object_reference )
{
// This line will not compile since `Foo0`, ... , `FooN` are non-polymorthic
Base* base_ptr = dynamic_cast <Base*> (&object_reference);
if ( base_ptr != nullptr )
{
// Construct from `Base`
return;
}
// Construct from `Foo0`, ... , `FooN`
}
template<typename type>
Derived::Derived ( const type& object_reference )
{
if
(
typeid(typename) == typeid(Foo0)
||
...
||
typeid(typename) == typeid(FooN)
}
{
// Construct from `Foo0`, ... , `FooN`
return;
}
else
{
// Construct from `Base`
// Here we should call `Base` members which `Foo0`, ... , `FooN` don't have
// so the following line will not compile
// object_reference.some_method();
// And we need to cast "&object_reference" to "Base*" what is not possible
// because `Foo0`, ... , `FooN` are not polimorthic
}
}
是否有任何有效的方法(第二节没有描述)来解决问题?
答案 0 :(得分:1)
根据评论中的信息,Foo1
和FooN
之间实际上存在共性,即它们都是套接字地址的编码。因此,在各种to_string()
类中进行FooAny
序列化,
class FooAny // Any runs from 1 to N
{
public:
std::string to_string() const { /* FooAny specific */ }
private:
// bla
};
然后在Derived
中使用一个模板构造函数,该构造函数委托给一个std::string
参数的常规构造者
class Derived
{
explicit Derived(std::string const& s): /* convert data members from string */ {}
template<class Foo>
explicit Derived(Foo const& f): Derived(f.to_string()) {} // delegating constructor
};
答案 1 :(得分:1)
您无需在此处使用typeid
:
2. Separating `Base` and `Derived` from others using `typeid`
为Foo类制作两个非模板ctors和一个模板ctor:
class Derived : public Base {
public:
Derived(const Derived&);
Derived(const Base&);
template<class Foo>
Derived(const Foo&);
};
答案 2 :(得分:1)
这是我的两分钱。 (Ideone.com上的Code)
#include <iostream>
#include <type_traits>
namespace so
{
struct _base_ {};
struct _foo1_{};
struct _foo2_{};
struct _foo3_{};
class _derived_: public _base_
{
public:
_derived_() = default;
_derived_(_derived_ const & _obj)
: _base_(_obj)
{
std::cout << "Constructed from _derived_" << std::endl;
}
_derived_(_base_ const & _obj)
: _base_(_obj)
{
std::cout << "Constructed from _base_" << std::endl;
}
template <typename _t_, typename = typename std::enable_if<
std::is_same<_t_, _foo1_>::value || std::is_same<_t_, _foo2_>::value ||
std::is_same<_t_, _foo3_>::value>::type>
_derived_(_t_ const &)
: _base_()
{
std::cout << "Constructed from _fooN_ using generic algorithm" << std::endl;
}
~_derived_() noexcept (true) = default;
};
} //namespace so
int main()
{
so::_base_ b_{};
so::_derived_ d_{};
so::_foo1_ f1_{};
so::_foo2_ f2_{};
so::_foo3_ f3_{};
so::_derived_ db_{b_};
so::_derived_ dd_{d_};
so::_derived_ df1_{f1_};
so::_derived_ df2_{f2_};
so::_derived_ df3_{f3_};
return (0);
}