2016-03-25 3 views
0

Рассмотрите следующие файлы заголовков.Как компилятор генерирует определения класса шаблонов?

В моем Object.h

#ifndef OBJECT_H_ 
#define OBJECT_H_ 

#include <iostream> 

template <class Policy> 
class Object 
{ 
    friend Policy; 
private: 
    Policy* p; 
    int hash; 

public: 
Object():p(new Policy(this)),hash(0){} 
    ~Object(){delete p;} 

    void set(){p->setHash();} 

    void show() const{std::cout<<"hash = "<<hash<<std::endl;} 
}; 

#endif // OBJECT_H_ 

Затем я создал две политики, P1 и P2, с различными значениями хэша.

В p1.h

#ifndef P1_H_ 
#define P1_H_ 

template <class Policy> class Object; 

class P1 
{ 
    enum {p1 = 1}; 
    Object<P1>* t; 

public: 
    P1(Object<P1>* at):t(at){} 
    void setHash(){t->hash = p1;} 
}; 

#endif // P1_H_ 

В p2.h

#ifndef P2_H_ 
#define P2_H_ 

template <class Policy> class Object; 
class P2 
{ 
enum {p2 = 2}; 

Object<P2>* t; 

public: 
P2(Object<P2>* at):t(at){} 
//void setHash(){t->hash = p2;} // ** Notice here ** 
}; 
#endif // P2_H_ 

В моей main.cpp меня

#include "Object.h" 
#include "p1.h" 
#include "p2.h" 

int main() 
{ 
    Object<P1> t1; 
    t1.set(); 
    t1.show(); 

    Object<P2> t2; 
    //t2.set(); 
    t2.show(); 
} 

Результат на OS X:

хэш = 1

хэш = 0

Наблюдения:

  1. Он будет компилировать и работать правильно. Обратите внимание, что определение Object<P2> еще не завершено. Поскольку P2 не определили setHash().

  2. Если я избавлюсь от комментария в моей основной, то он сообщит об ошибке.

    ./Object.h:20:8: ошибка: ни один член с именем 'setHash' в 'P2'

    main.cpp: 12: 6: Примечание: в конкретизации функции члена «Object :: набор 'запрошен здесь t2.set();

Вопросы

  1. Рассмотрим элемент объекта внутри P1 или класса P2 бы компилятор генерировать определение класса для каждого из них, даже если я не создаю экземпляр Object<P1> или Object<P2 в основной?

  2. Почему Object<P2> в порядке? Поскольку определение неполное.

+0

"тогда он сообщит об ошибке" Что? – user657267

+0

@ пользователь657267 выше. – Ling

ответ

1

Consider the Object member inside P1 or P2 class would compiler generate class definition for each of them even if I do not create an instance of Object<P1> or Object<P2> in main?

No. Члены являются Object<P1>* t; и Object<P1>* t; - они не static так создается только при создании P1 и P2 экземпляров объектов, и они указатели, так что даже тогда не Object<P1>* не создается: указатель, переданный к конструктору, который может быть nullptr/0 - просто хранится.

Why Object is OK? Since the definition is incomplete.

С помощью шаблонов функции создаются только при вызове. Пока они могут быть правильно проанализированы, это не ошибка.

+0

Спасибо. Я вижу сейчас. – Ling

1

Там нет Object<P1> или Object<P2> членов внутри P1 и P2. Есть Object<P1>* и Object<P2>* пользователей. Указатель на неполный тип - отлично. Сам тип не будет создан, если указатель не будет разыменован.

В вашей функции mainObject<P2> является полным типом, но его не виртуальные функции-члены по-прежнему не создаются, если не вызваны (точнее, технически, используются ODR). Вот почему это нормально, если Object<P2> t2;, но при вызове t2.set() есть ошибка.

+0

Спасибо вам и Тони Д. – Ling

Смежные вопросы