2017-01-31 5 views
0

Я столкнулся с этим шаблоном класса интеллектуальных указателей Cptr, показанным частично ниже, и я не понимаю одну из реализаций метода и надеялся получить некоторый вклад. Мой вопрос: «Способ 2», обозначенный ниже. В частности, если Cptr шаблонизирован T, какой синтаксис вызова доступен, что позволяет вызывать метод 2, который, по крайней мере, для меня, является конструктором копирования, но я думал, что конструкторы копирования не являются шаблонами.Templated Class "Copy Constructor"

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; 
} 

я предполагал вызов метода 2 следующим образом:

Cptr<float> B(new float(1.1)); 
Cptr<int> A(B); //error for different types 

Но назначение указателей разных типов не имеет большого смысла для меня. Кто-нибудь сталкивался с определением метода, таким как «Метод 2», и если да, то каковы его применения? Большое спасибо за ваше время.

ответ

3

Прежде всего, конструкторы копирования, безусловно, могут быть шаблоном, свободно говорящим. Технически конструктор копирования является конструктором из другого экземпляра того же класса, но вы, безусловно, можете определить конструктор, который ссылается на другой класс в качестве параметра.

Однако ответ на ваш основной метод является то, что «Method2» позволяет смарт-указатель будет выделено из интеллектуального указателя к другому классу, до тех пор, как подразумевается преобразование типов допускается:

class Base {}; 

class Derived : public Base {}; 

Cptr<Derived> d; 

Cptr<Base> b=d; // "Method2" will be used here. 

Эта реализация интеллектуального указателя позволяет интеллектуальному указателю на производный класс назначаться интеллектуальному указателю на базовый класс.

Обычно Cptr<Base> и Cptr<Derived> - это два совершенно несвязанных класса. Каждый экземпляр шаблона представляет собой отдельный класс. И вы обычно не можете назначать экземпляр одного класса экземпляру совершенно несвязанного класса, если только подходящее преобразование не доступно.

Так же, как вы можете назначить обычный указатель на производный класс указателю на базовый класс, этот интеллектуальный указатель обеспечивает сопоставимую функциональность.

+7

Формально копии конструкторов не могут быть шаблонами (** 12.8 [класс.копия] **) – juanchopanza

+0

Хорошо, справедливо; изменил формулировку. –

+0

Неправильное использование. Используется неявное преобразование указателя, а не неявное преобразование самих типов. Поэтому он работает только с иерархией классов. Изменить: вы удалили этот раздел. –

2

Прежде всего, вы правы. Конструкторы копирования не могут быть шаблонами. §12.8/2 говорит (акцент сам):

нешаблонном конструктор для класса X является конструктор копирования, если его первый параметр имеет тип X&, const X&, volatile X& или const volatile X&, а также там никаких других параметров или иначе все остальные параметры по умолчанию аргументы [...]

Но метод 2 не конструктор копирования, потому что Cptr<S> это другой класс, чем Cptr<T>. Это просто нормальный конструктор, который не очень сильно отличается от, скажем, Cptr(int i) или Cptr(std::string const& s). И обычные конструкторы могут быть шаблонами.

Конечно, вы можете предположить, что Cptr<U> будет содержать те же элементы, что и Cptr<T>. Это то, что делает реализация конструктора. Это не сработало бы, например, если Cptr был специализирован для этого U, и эти члены не существовали.