C++ 模板类“;复制构造函数“;

C++ 模板类“;复制构造函数“;,c++,C++,我遇到了下面部分显示的模板化智能指针类Cptr,我不理解其中一个方法实现,希望得到一些输入。我的问题是关于“方法2”,标签如下。具体地说,如果Cptr是由T模板化的,那么允许调用“方法2”的调用语法是什么呢?至少在我看来,它是一个复制构造函数,但我认为复制构造函数不是模板化的 template <class T> class Cptr { public: /* Constructors ... */ /* Getters ... */

我遇到了下面部分显示的模板化智能指针类Cptr,我不理解其中一个方法实现,希望得到一些输入。我的问题是关于“方法2”,标签如下。具体地说,如果Cptr是由T模板化的,那么允许调用“方法2”的调用语法是什么呢?至少在我看来,它是一个复制构造函数,但我认为复制构造函数不是模板化的

template <class T> class Cptr
{
    public:

        /* Constructors ... */

        /* Getters ... */
        T* ptr() const { return p_; }
        long* cnt() const { return cnt_; }

        /* Copy Constructors? */
        //Method 1
        Cptr<T>(const Cptr<T>& i) 
            : ptr_(i.ptr()), cnt_(i.ptr())
        {
            std::cout << "M1" << std::endl;
            ++(*cnt);
        }

        //Method 2
        template <class S> Cptr(const Cptr<S>& i) 
            : ptr_(i.get()), cnt_(i.cnt())
        {
            std::cout << "M2" << std::endl;
            ++(*cnt_);
        }

    private:
        T* p_;
        int* cnt_;
};

int main(int argc, char* argv[])
{

    CPtr<int> A(new int(5));
    CPtr<int> B(A);

    std::cout << *(B.get()) << std::endl;

    return EXIT_SUCCESS;
}
模板类Cptr
{
公众:
/*构造器*/
/*吸气剂*/
T*ptr()常量{return p;}
long*cnt()常量{return cnt_;}
/*复制构造函数*/
//方法1
Cptr(常数Cptr&i)
:ptr_(i.ptr()),cnt_(i.ptr())
{

std::cout首先,松散地说,复制构造函数当然可以是一个模板。从技术上讲,复制构造函数是来自同一类的另一个实例的构造函数,但您当然可以定义一个将对另一个类的引用作为参数的构造函数

但是,主要方法的答案是“Method2”允许将智能指针从智能指针分配到不同的类,只要允许隐含的类型转换:

class Base {};

class Derived : public Base {};

Cptr<Derived> d;

Cptr<Base> b=d; // "Method2" will be used here.
类基{};
派生类:公共基{};
Cptr d;
这里将使用Cptr b=d;//“Method2”。
此智能指针实现允许将指向派生类的智能指针分配给指向基类的智能指针

通常,
Cptr
Cptr
是两个完全不相关的类。每个模板实例都是一个单独的类。除非有适当的转换,否则通常不能将一个类的实例分配给一个完全不相关的类的实例


就像您可以将派生类的普通指针指定给基类的指针一样,这个智能指针提供了类似的功能。

首先,复制构造函数可以是一个模板,不严格地说。从技术上讲,复制构造函数是来自同一类的另一个实例的构造函数,但您当然可以定义将对另一个类的引用作为参数的构造函数

但是,主要方法的答案是“Method2”允许将智能指针从智能指针分配到不同的类,只要允许隐含的类型转换:

class Base {};

class Derived : public Base {};

Cptr<Derived> d;

Cptr<Base> b=d; // "Method2" will be used here.
类基{};
派生类:公共基{};
Cptr d;
这里将使用Cptr b=d;//“Method2”。
此智能指针实现允许将指向派生类的智能指针分配给指向基类的智能指针

通常,
Cptr
Cptr
是两个完全不相关的类。每个模板实例都是一个单独的类。除非有适当的转换,否则通常不能将一个类的实例分配给一个完全不相关的类的实例


正如您可以将指向派生类的普通指针指定给指向基类的指针一样,此智能指针提供了类似的功能。

首先,您是对的。复制构造函数不能是模板。§12.8/2说(我强调):

X
非模板构造函数如果其 第一个参数的类型为
X&
const X&
volatile X&
const volatile X&
,要么没有其他参数,要么所有其他参数 参数具有默认参数[…]

但是方法2不是一个复制构造函数,因为
Cptr
Cptr
是一个不同的类。它只是一个普通的构造函数,与
Cptr(inti)
Cptr(std::string const&s)
没有太大区别。普通的构造函数可以是模板


当然,您可以假设
Cptr
将具有与
Cptr
相同的成员。这就是构造函数的实现所做的。例如,如果
Cptr
专门用于该
U
而这些成员不存在,那么它将不起作用。

首先,您是对的。复制构造函数不可能存在铭牌§12.8/2规定(本人强调):

X
非模板构造函数如果其 第一个参数的类型为
X&
const X&
volatile X&
const volatile X&
,要么没有其他参数,要么所有其他参数 参数具有默认参数[…]

但是方法2不是一个复制构造函数,因为
Cptr
Cptr
是一个不同的类。它只是一个普通的构造函数,与
Cptr(inti)
Cptr(std::string const&s)
没有太大区别。普通的构造函数可以是模板


当然,您可以假设
Cptr
将具有与
Cptr
相同的成员。这就是构造函数的实现所做的。例如,如果
Cptr
专门用于该
U
而这些成员不存在,那么它将不起作用。

正式复制构造函数不能是模板(12.8)[class.copy])好的,很公平;调整了措辞。这是不正确的。使用的是指针的隐式转换,而不是类型本身的隐式转换。因此,它只适用于类层次结构。编辑:您删除了该节。@juanchopanza因为它只处理指针,所以可以进行复制,因为它们在p中是一致的平台(又名32位整数大小或64位等)。我的假设不正确吗?@Nas.A.您可能想向Jean-Bernard说明这一点。正式的复制构造函数不能是模板(12.8[class.copy])好的,很公平;调整了措辞。这是不正确的。使用了指针的隐式转换,而不是模板的隐式转换