2014-01-10 138 views
1

我最近遇到一个实例,在这个实例中,我意识到我编写的几个类共享了很多功能。我意识到我可以将这些类推广到具有一些模板参数的公共基础中。问题是这些类有大约20种不同的重载构造函数,其中大多数类的功能都被实现。用我想出了解决方案来说明:C++ 11通过可变参数模板继承的构造函数

template <typename T> 
class Base { 

    protected: 

    T member_; 

    public: 

    Base(int a) { /* ... */ } 

    Base(double a) { /* ... */ } 

    Base(char a) { /* ... */ } 

    Base(int a, double b, char c) { /* ... */ } 

    // etc... 

}; 

class Derived1 : public Base<int> { 

    public: 

    template <typename... Args> 
    Derived1(Args... args) : Base(args...) { } 

    // other constructors specific to Derived1 

}; 

class Derived2 : public Base<char> { 

    public: 

    template <typename... Args> 
    Derived2(Args... args) : Base(args...) { } 

    // other constructors specific to Derived2 

}; 

我这里有几个问题:

  1. 是否有与此相关的任何运行时性能损失? (环顾四周后,好像我应该在派生类中使用右值引用和std::forward,对吧?)
  2. 从代码可维护性的角度来看,这是一个好主意吗?
  3. 这种方法有什么缺陷? (例如,其他地方的类似示例似乎正在使用explicit关键字。为什么?)
  4. 是否有更好,更标准,更安全或更可读的方式来执行此操作?

回答

3
  1. 是的,你应该用完美转发。如果构造函数声明为内联,则性能影响为零。

  2. 这是一个“可怕的模板”,但很容易被模板知道的人识别。取决于你的维护者,我猜?

  3. 您需要小心拦截用于派生类的复制和移动构造函数的调用,因为您的可变参数完美转发签名匹配所有内容。通过enable_if正确约束通常需要比转发构造函数本身更多的代码。

  4. 继承构造函数是“更好”的方法。指定该功能是为了避免捕获应该转到派生类构造函数的签名。编译器的支持可能是不确定的:这不是最容易实现的特性,也不是最需要的特性,因此实现者在一段时间内推迟了这一点。

4

在C++ 11中,构造函数可以被继承。

https://stackoverflow.com/a/434784/232574

+0

是否存在与继承构造函数相关的运行时间惩罚,因为您在跳过更多(与复制构造函数相比,与我的版本相比)?编译器对此功能的支持如何? –

+0

没有运行时间损失。这只是编译器基本上将基础构造函数转发给派生的简写。查看http://stackoverflow.com/questions/9979194/what-is-constructor-inheritance获取更多信息 –

+0

谢谢。两个答案都很好。我现在接受了另一个,但我认为这个问题的未来观众将从这里得到两个答案中受益。 –