2

一、问题描述:

班级Derived是班级的孩子Base。你不能修改类Base。定义构造函数和赋值运算符,Derived以便可以从以下实例构造它:

  • Base1

  • Derived1

  • N非多态且不相关的类型Foo1,...,FooN2

1从两者构造BaseDerived使用Base复制构造函数完成。

2Foo1所有, ...的构造FooN是由通用算法完成的。

二、可能的解决方案:

1.蛮力:

N+1单独的构造函数 +N+1单独的赋值运算符。绝对不优雅。大量无用的代码:N+1标头中的方法声明 +N+1源中的方法实现。未使用模板的力量。

2. 有类型限制的模板构造函数

声明和定义常规复制构造函数

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在源代码中实现方法。无论如何,我相信有更好的解决方案。

三、什么不起作用:

1. 使用 `dynamic_cast` 将 `Base` 和 `Derived` 与其他人分开

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`

}

2. 使用 `typeid` 将 `Base` 和 `Derived` 与其他人分开

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

    }

}

四。问题:

有没有在第二节中没有描述的有效方法来解决这个问题?

4

3 回答 3

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
};
于 2013-08-23T08:52:35.283 回答
1

你不需要在typeid这里使用:

2. Separating `Base` and `Derived` from others using `typeid`

只需为 Foo 类制作两个非模板 ctor 和一个模板 ctor:

class Derived : public Base {
 public:
  Derived(const Derived&);
  Derived(const Base&);

  template<class Foo>
  Derived(const Foo&);
};
于 2013-08-23T09:14:34.743 回答
1

这是我的两分钱。(Ideone.com上的代码)

#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);
}
于 2013-08-23T09:18:14.680 回答