#c #templates #one-definition-rule
#c #шаблоны #одно определение-правило
Вопрос:
Вопрос в том, что в случае создания шаблона из класса с помощью шаблонов, затем включите его для использования как обычно: будет получена ошибка, описанная ниже:
Если требуется использовать struct что-либо прямолинейно в Node.inl. Он должен включать заголовок «Node.h» следующим образом, но это приведет к некоторым проблемам. Мы нарушаем правило одного определения, но шаблонный класс должен включать свои определения в тот же файл, в котором они объявлены. В противном случае компилятор забудет указать функции-члены при создании экземпляра. В результате мы не можем использовать эти функции через инициализированный экземпляр. Итак, как мы можем управлять этим, хотя мы хотим сохранить разделенность объявлений и определений, сохраняем, не нарушая одно правило определения?
Node.inl:
#include "Node.h"
void foo(){
struct Something s{1, 2};
}
template <class T>
Node<T>::Node(int data, Node<T> *next) : m_data{data}, m_next{next} {}
template <class T>
void Node<T>::setData(int data) {
m_data = data;
}
template <class T>
int Node<T>::getData() const {
return m_data;
}
template <class T>
void Node<T>::setNext(Node<T> *next) {
m_next = next;
}
template <class T>
Node<T> * Node<T>::getNext() const {
return m_next;
}
template <class T>
void Node<T>::allocMemoryNext() {
m_next = new Node<T>();
}
Node.h:
#ifndef THE1_NODE_H
#define THE1_NODE_H
struct Something{
int x;
int y;
};
template <class T>
class Node {
private:
T m_data;
Node *m_next;
public:
explicit Node(int data = 0, Node *next = nullptr);
void setData(int data);
[[nodiscard]] int getData() const;
void setNext(Node *next);
[[nodiscard]] Node *getNext() const;
void allocMemoryNext();
};
#include "Node.inl"
#endif //THE1_NODE_H
Ответ №1:
мы хотим сохранить разделенность объявлений и определений
В том, что касается шаблонов, такой «разделенности» нет. Для того, чтобы кто-либо мог их использовать, они должны быть определены. И Node.h предоставляет эти определения.
Node.inl является частью Node.h. Вы логически разделили текст на разные файлы, но они не являются отдельными, насколько это касается какой-либо практической реальности. Каждый пользователь Node.h также должен получать материал Node.inl, поэтому вы #include "Node.inl"
в конце файла. Никто, кроме Node.h, не должен включать Node.inl, поэтому нет причин для Node.inl #include "Node.h"
.
Таким образом, проблем нет, как только вы удалите ненужное включение вещи, которая определенно уже существует.
Комментарии:
1. Но я могу захотеть использовать структуру, которая определена в «Node.h» в «Node.inl», поэтому мне нужно включить. На самом деле, это то, о чем спрашивают.
2. @ibrahimkoz: Нет, вам не нужно включать ничего подобного. Файлы в C не являются отдельной, заблокированной конструкцией.
#include
sion — это просто копирование / вставка текста из одного файла в другой. Node.inl включен после множества определений в Node.h, поэтому у него есть к ним доступ.3. Нет, вы ошибаетесь, классы и структуры должны быть включены для использования на месте.
4. @ibrahimkoz: Их не нужно «включать»; они должны быть видимыми . И они видны. Удалите
#include "Node.h"
из вашегоNode.inl
файла, и вы обнаружите, что он может видетьSomething
просто отлично. При условии, чтоNode.h
это единственный файл, который включаетNode.inl
.5. Нет, в этом случае вы не можете получить доступ к элементам чего-либо. Таким образом, вы ничего не можете сделать, пока можете это видеть.