Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.12.2018, 16:45   #1
Anton_Jag
Пользователь
 
Регистрация: 05.11.2009
Сообщений: 41
По умолчанию Ошибка линковщика

Делаю небольшую бд основанную на шаблонном списке и классах.
LinkedList.h
Код:
#pragma once
#include <iostream> 
#include <string> 

template<typename T>
struct Node
{
	T data;
	Node* next;
};

template<typename T>
class LinkedList
{
private:

	Node<T>* head;
	Node<T>* tail;
	int size;

public:
	LinkedList() : head{ nullptr }, tail{ nullptr }, size{ 0 }
	{
	}
	~LinkedList() {
		Node<T>* currentNode = head;

		while (currentNode != tail)
		{
			Node<T>* nextNode = currentNode->next;
			delete currentNode;
			currentNode = nextNode;
		}
		delete currentNode;
	}
	Node<T>* createNode(T data);
	void display();
	void push(T data);
	Node<T>* findNode(T data);
	Node<T>* getNodeById(int id);
	int getSize();
	void delNode(Node<T>* node);
};
LinkedList.cpp
Код:
#include "pch.h"
#include "LinkedList.h"

template<typename T>
Node<T>* LinkedList<T>::createNode(T data)
{
	Node<T>* newNode = new Node<T>;
	newNode->data = data;
	newNode->next = nullptr;

	return newNode;
}

template<typename T>
void LinkedList<T>::display()
{
	Node<T>* currentNode = head;

	while (currentNode)
	{
		std::cout << currentNode->data << std::endl;
		currentNode = currentNode->next;
	}
}

template<class T>
void LinkedList<T>::push(T data)
{
	Node<T>* newNode = createNode(data);

	if (size == 0)
	{
		head = newNode;
		tail = newNode;
	}
	else
	{
		tail->next = newNode;
		tail = newNode;
	}

	++size;
}

template<typename T>
Node<T>* LinkedList<T>::findNode(T data)
{
	Node<T>* currentNode = head;

	while (currentNode)
	{
		if (currentNode->data == data)
			return currentNode;
		currentNode = currentNode->next;
	}
	return nullptr;
}

template<typename T>
Node<T>* LinkedList<T>::getNodeById(int id)
{
	if(id > size) return nullptr;
	Node<T>* currentNode = head;

	while (id < size)
		currentNode = currentNode->next;
	return currentNode;
}

template<typename T>
int LinkedList<T>::getSize()
{
	return size;
}

template<typename T>
void LinkedList<T>::delNode(Node<T>* node)
{
	if (node == nullptr) return;

	if (node == head) {
		head = head->next;
		delete node;
	}

	Node<T>* currentNode = head;

	while (currentNode->next) {
		if (currentNode->next == node) {
			currentNode->next = node->next;
			delete node;
		}
		currentNode = currentNode->next;
	}
}
People.h
Код:
#pragma once
#include <string>
using namespace std;

class People
{
protected:
	string name;
public:
	People();
	People(string name) : name{ name } {}
	string getName();
	void setName(string name);
	virtual ~People() = 0;
};
People.cpp
Код:
#include "pch.h"
#include "People.h"


People::People()
{
}

string People::getName()
{
	return name;
}

void People::setName(string name)
{
	this->name = name;
}
Student.h
Код:
#pragma once
#include "People.h"
#include "Predmet.h"
#include "LinkedList.h"

struct Match {
	Predmet* predmet;
	short mark;
	bool operator==(Match other) { return predmet == other.predmet; }
};

class Student :
	public People
{
private:
	int count;
	LinkedList<Match>* matches;
public:
	Student();
	Student(string name) : People{ name } { count = 0; matches = new LinkedList<Match>(); };
	int getCount();
	void setCount(int count);
	void addMatch(Predmet* predmet, short mark);
	void changeMatch(Predmet* predmet, short mark);
	void delMatch(Predmet* predmet);
	float getAvg();
	~Student();
};
Student.cpp
Код:
#include "pch.h"
#include "Student.h"


Student::Student()
{
	count = 0; matches = new LinkedList<Match>();
}

int Student::getCount()
{
	return count;
}

void Student::setCount(int count)
{
	this->count = count;
}

void Student::addMatch(Predmet * predmet, short mark)
{
	Match match;
	match.mark = mark;
	match.predmet = predmet;
}

void Student::changeMatch(Predmet * predmet, short mark)
{
	Match tmp;
	tmp.predmet = predmet;
	Match match = matches->findNode(tmp)->data;
	match.mark = mark;
}

void Student::delMatch(Predmet * predmet)
{
	Match tmp;
	tmp.predmet = predmet;
	matches->delNode(matches->findNode(tmp));
}

float Student::getAvg()
{
	float avg = 0;
	for (int i = 1; i <= matches->getSize(); i++)
		avg += matches->getNodeById(i)->data.mark;
	return avg / matches->getSize();
}


Student::~Student()
{
	delete matches;
}
Predmet.h
Код:
#pragma once
#include <string>
using namespace std;

class Predmet
{
private:
	string name;
public:
	Predmet();
	Predmet(string name) : name{name} {};
	~Predmet();

	string getName() { return name; }
	void setName(string name) { this->name = name; }
};



Predmet::Predmet()
{
}


Predmet::~Predmet()
{
}
и мейн
Код:
#pragma once
#include "pch.h"
#include <iostream>
#include "LinkedList.h"

#include "Prepod.h"
#include "Student.h"

int main()
{
	system("chcp 1251");
	LinkedList<People*> a;
	Student* st = new Student("карл");
	Prepod* pr = new Prepod("марк");
	a.push(st);
	a.push(pr);
	a.display();
	system("pause");
	return 0;
}
При компиляции получаю
LNK2005: "public: __thiscall Predmet::Predmet(void)" (??0Predmet@@QAE@XZ) уже определен в Journal.obj
1>Student.obj : error LNK2005: "public: __thiscall Predmet::~Predmet(void)" (??1Predmet@@QAE@XZ) уже определен в Journal.obj
1>Journal.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: virtual __thiscall People::~People(void)" (??1People@@UAE@XZ) в функции __unwindfunclet$??0Student@@QAE@V?$ basic_string@DU?$char_traits@D@std@ @V?$allocator@D@2@@std@@@Z$2
1>Prepod.obj : error LNK2001: неразрешенный внешний символ ""public: virtual __thiscall People::~People(void)" (??1People@@UAE@XZ)"
1>Student.obj : error LNK2001: неразрешенный внешний символ ""public: virtual __thiscall People::~People(void)" (??1People@@UAE@XZ)"
1>Journal.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: void __thiscall LinkedList<class People *>:isplay(void)" (?display@?$LinkedList@PAVPeople@@@ @QAEXXZ) в функции _main
1>Journal.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: void __thiscall LinkedList<class People *>:ush(class People *)" (?push@?$LinkedList@PAVPeople@@@@QA EXPAVPeople@@@Z) в функции _main
1>Student.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: struct Node<struct Match> * __thiscall LinkedList<struct Match>::findNode(struct Match)" (?findNode@?$LinkedList@UMatch@@@@Q AEPAU?$Node@UMatch@@@@UMatch@@@Z) в функции "public: void __thiscall Student::changeMatch(class Predmet *,short)" (?changeMatch@Student@@QAEXPAVPredm et@@F@Z)
1>Student.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: struct Node<struct Match> * __thiscall LinkedList<struct Match>::getNodeById(int)" (?getNodeById@?$LinkedList@UMatch@@ @@QAEPAU?$Node@UMatch@@@@H@Z) в функции "public: float __thiscall Student::getAvg(void)" (?getAvg@Student@@QAEMXZ)
1>Student.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: int __thiscall LinkedList<struct Match>::getSize(void)" (?getSize@?$LinkedList@UMatch@@@@QA EHXZ) в функции "public: float __thiscall Student::getAvg(void)" (?getAvg@Student@@QAEMXZ)
1>Student.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: void __thiscall LinkedList<struct Match>:elNode(struct Node<struct Match> *)" (?delNode@?$LinkedList@UMatch@@@@QA EXPAU?$Node@UMatch@@@@@Z) в функции "public: void __thiscall Student:elMatch(class Predmet *)" (?delMatch@Student@@QAEXPAVPredmet@ @@Z)
1>C:\Users\1\Documents\Visual Studio 2017\Projects\Journal\Debug\Journal .exe : fatal error LNK1120: неразрешенных внешних элементов: 7
1>Сборка проекта "Journal.vcxproj" завершена с ошибкой.
Anton_Jag вне форума Ответить с цитированием
Старый 26.12.2018, 16:54   #2
Anton_Jag
Пользователь
 
Регистрация: 05.11.2009
Сообщений: 41
По умолчанию

C People разобрался добавив реализацию деструктора
Код:
People::~People()
{
}
Anton_Jag вне форума Ответить с цитированием
Старый 26.12.2018, 16:55   #3
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Либо шаблоны полностью запихните в хедер, либо явно инстанцируйте нужный.
p51x на форуме Ответить с цитированием
Старый 26.12.2018, 17:41   #4
Anton_Jag
Пользователь
 
Регистрация: 05.11.2009
Сообщений: 41
По умолчанию

Добавил
Код:
template void LinkedList<People*>::display();
template void LinkedList<Student*>::display();
template void LinkedList<Predmet*>::display();
template void LinkedList<People*>::push(People*);
template int LinkedList<Match>::getSize();
template Node<Match>* LinkedList<Match>::getNodeById(int);
template Node<Match>* LinkedList<Match>::findNode(Match);
template void LinkedList<Match>::delNode(Node<Match>*);
и все скомпилировалось. однако a.display(); выводит адрес ссылки, хотя я перегрузил операторы вывода для классов Student и Prepod
Код:
std::ostream & operator<<(std::ostream & out, const Student & student)
{
	Student a = student;
	out << student.name << "  Средний балл - " << a.getAvg() << endl;
	return out;
}
Anton_Jag вне форума Ответить с цитированием
Старый 26.12.2018, 18:01   #5
Anton_Jag
Пользователь
 
Регистрация: 05.11.2009
Сообщений: 41
По умолчанию

Т.е. нужно чтобы при вызове
Код:
std::cout << currentNode->data << std::endl;
вызывался соот оператор класса потомка
Anton_Jag вне форума Ответить с цитированием
Старый 26.12.2018, 18:34   #6
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 1,772
По умолчанию

https://stackoverflow.com/questions/...-child-classes
Black Fregat вне форума Ответить с цитированием
Старый 26.12.2018, 21:33   #7
Anton_Jag
Пользователь
 
Регистрация: 05.11.2009
Сообщений: 41
По умолчанию

в функции findNode при разыменовывании *currentNode->data ругается недопустимое косвенное обращение, при этомв функции display аналогичная вещь работает нормально. как так?
Код:
template<typename T>
void LinkedList<T>::display()
{
	Node<T>* currentNode = head;

	while (currentNode)
	{
		std::cout << *currentNode->data << std::endl;
		currentNode = currentNode->next;
	}
}

template<typename T>
void LinkedList<T>::push(T data)
{
	Node<T>* newNode = createNode(data);

	if (size == 0)
	{
		head = newNode;
		tail = newNode;
	}
	else
	{
		tail->next = newNode;
		tail = newNode;
	}

	++size;
}

template<typename T>
Node<T>* LinkedList<T>::findNode(T data)
{
	Node<T>* currentNode = head;

	while (currentNode)
	{
		//std::cout << *(currentNode->data) << std::endl;
		if (*currentNode->data == *data)
			return currentNode;
		currentNode = currentNode->next;
	}
	return nullptr;
}
Anton_Jag вне форума Ответить с цитированием
Старый 26.12.2018, 22:17   #8
Anton_Jag
Пользователь
 
Регистрация: 05.11.2009
Сообщений: 41
По умолчанию

Разобрался. Нужно хранить в списке только ссылки а у меня в одном месте объявляется список объектов, поэтому вызывало ошибку.
Anton_Jag вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка сценария в Visual Studio. На этой странице произошла ошибка скрипта. Ошибка: разрешение отклонено. Код 0. Мaкс Windows 15 13.11.2022 12:25
Ошибка линковщика darkblood0202 C++ Builder 2 23.04.2012 19:05
Где ошибка в этом исходном коде на языке Си? Или ошибка в Excel? ArchiCurtis Помощь студентам 2 07.04.2012 14:16
Шаблоны - ошибка линковщика Сtrl Общие вопросы C/C++ 8 24.04.2011 11:46
Ошибка в коде, ошибка в css или это проблема с совместимостью с браузерами? ankris HTML и CSS 5 23.11.2010 16:58