2014-05-13 170 views
1

我有一个模板类C.我想要这样的模板拷贝构造函数,它将根据其他类的大小调整数据数组的大小。用模板拷贝构造函数替换默认拷贝构造函数

以下是一个简单的例子。它工作正常。但是,请注意,Constructor 2Constructor 3如此相似,我想知道是否可以将它们合并为一个?

另外,如果我简单地删除Constructor 3,那么C<int> c3(c1)将不会调用Constructor 2,而是调用编译器添加的默认拷贝构造函数。这将导致内存分配不当。

template<typename T> 
class C 
{ 
public: 
    T* val; 
    int size; 
public: 

    C(int s = 0) { 
     cout << "Constructor 1" << endl; 
     size = s; 
     val = (size) ? new T[size] : nullptr; 
    } 

    template<class T2> 
    C(const C<T2>& c2) { 
     cout << "Constructor 2" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 

    C(const C<T>& c2) { 
     cout << "Constructor 3" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 

    ~C() { 
     cout << "~C()" << endl; 
     delete[] val; 
     val = nullptr; 
    } 
}; 

int main(void) 
{ 
    C<int> c1(5); 
    C<float> c2(c1); 
    C<int> c3(c1); 

    return 0; 
} 

上述功能的输出:

Constructor 1 
Constructor 2 
Constructor 3 
~C() 
~C() 
~C() 
+1

您可以在C++ 11中使用构造函数委托,也可以使用执行此初始化的成员函数(helper)。 – dyp

+0

假设你想对你正在分配的内存做一些有用的事情,构造函数2将使用来自源类型的对象做什么? – Praetorian

+0

你打算在这些构造函数中执行'c2.val'元素的副本吗? – dyp

回答

1

通过

template<class T2> 
C(const C<T2>& c2, int dummy) { 
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

template<class T2> 
C(const C<T2>& c2) : C(c2, 0) {} 

C(const C<T>& c2) : C(c2, 0) {} 

更新替换

template<class T2> 
C(const C<T2>& c2) { 
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

C(const C<T>& c2) { 
    cout << "Constructor 3" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

你可以使用:

C(int s = 0) { 
    cout << "Constructor 1" << endl; 
    size = s; 
    val = (size) ? new T[size] : nullptr; 
} 

template<class T2> 
C(const C<T2>& c2) : C(c2.size) {} 

C(const C<T>& c2) : C(c2.size) {} 

而不需要第二个构造函数。

+0

它不那么优雅。但是,似乎这是摆脱这种情况的唯一方法。 –

+0

@YuchenZhong查看我的更新。 –

+0

通常,使用一种特殊的专用类作为虚拟的类型和作出这样的构造函数私有。这可以防止超载问题(类的用户无意中调用该ctor)。 – dyp

0

一个想和一个C++ 11委派构造来实现此。然而,由于模板参数对于类或构造函数是不明确的,所以这不可能以直接的方式进行。作为一种解决方法,可以将通用代码分解为辅助函数。

类似:

template<class T2> 
    C(const C<T2>& c2) { 
     Copy<T2>(c2); 
    } 

    C(const C<T>& c2) { 
     Copy<T>(c2); 
    } 

private: 
    template<class T2> 
    void Copy(const C<T2>& c2) { 
     cout << "Constructor 2" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 
+1

很确定第二个构造函数是委托给自己的。编辑:[是的,这是](http://coliru.stacked-crooked.com/a/c052b789d02eddef)。有趣的是,clang检测到并抛出错误,而gcc segfaults。 – Praetorian

+0

@Praetorian:是的,你是对的。我正试图让大局出来。但是,没有解决模板参数的问题。顺便说一句,在VS你会得到“成功”的建设,除非你把警告视为错误。我用一些不同的东西更新了答案,不会改变第二个ctor的签名。 – Apriori