C++ для бегинеров

User avatar
Сабина
Уже с Приветом
Posts: 19045
Joined: 11 Jan 2012 09:25
Location: CA

C++ для бегинеров

Post by Сабина »

Вот спрашиваю, как и грозилась :).

Умом понимаю о чем ошибка, но не пойму почему в Интернете 33 примера где делают как я и у них все работает :D

Есть такой класс. А компаратор не хочет компилироваться

Code: Select all

// Employee.h
#ifndef Employee_H
#define Employee_H
#include <string>
#include <iostream>

using namespace std;

class Employee
{
private:
	int employeeId;
	string firstName;
	string lastName;
	int age;
	string department;
	string position;

public:
	Employee();
	Employee(int id, string firstN, string lastN);
    Employee(int id, string firstN, string lastN, int age);
    Employee(int id, string firstN, string lastN, int age, string dept, string pos);
	virtual ~Employee();
	void setEmployeeId(int id);
	void setFirstName(string n);
	void setLastName(string n);
	void setAge(int eAge);
	void setDepartment(string dept);
	void setPosition(string pos);
	int getEmployeeId() const;
	string getFirstName() const;
	string getLastName() const;
	int getAge() const;
	string getDepartment() const;
	string getPosition() const;
	bool operator<(const Employee& e);
	friend std::ostream &operator << (std::ostream &os, Employee const &m) {
		return std::cout << m.employeeId << " " << m.firstName << " " << m.lastName  << "\n";
	}
};

#endif

Code: Select all

#include "Employee.h"
#include <sstream>
#include <iostream>
#include <string>

	Employee::Employee()
	{
		employeeId = 0;
		firstName = " ";
		lastName = " ";
		age = 0;
		department = " ";
		position = " ";
	}

Employee::Employee(int id, string firstN, string lastN)
	{
		employeeId = id;
		firstName = firstN;
		lastName = lastN;
		age = 0;
		department = " ";
		position = " ";
	}

	Employee::Employee(int id, string firstN, string lastN, int age)
	{
		employeeId = id;
		firstName = firstN;
		lastName = lastN;
		age = age;
		department = " ";
		position = " ";
	}

	Employee::Employee(int id, string firstN, string lastN, int age, string dept, string pos)
	{
		employeeId = id;
		firstName = firstN;
		lastName = lastN;
		age = age;
		department = dept;
		position = pos;
	}


	Employee::~Employee()
	{
	}

	void Employee::setEmployeeId(int id)
	{
		employeeId = id;
	}

	void Employee::setFirstName(string n)
	{
		firstName = n;
	}

	void Employee::setLastName(string n)
	{
		lastName = n;
	}

	void Employee::setAge(int eAge)
	{
		age = eAge;
	}

	void Employee::setDepartment(string dept)
	{
		department = dept;
	}

	void Employee::setPosition(string pos)
	{
		position = pos;
	}

	int Employee::getEmployeeId() const
	{
		return employeeId;
	}

	string Employee::getFirstName() const
	{
		return firstName;
	}

	string Employee::getLastName() const
	{
		return lastName;
	}

	int Employee::getAge() const
	{
		return age;
	}

	string Employee::getDepartment() const
	{
		return department;
	}

	string Employee::getPosition() const
	{
		return position;
	}

	bool Employee::operator < (const Employee& e) {
		return employeeId < e.employeeId;
	}

Code: Select all

// project1.cpp : Defines the entry point for the console application.
//

#include "Employee.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

class EmployeeComparator
{
	bool operator()(const Employee& a, const Employee& b)
	{
		return a.getEmployeeId < b.getEmployeeId;
	}
};

int main()
{

	Employee employeeList[5] = {
	Employee(3, "John", "Reed",25 , "accounting", "clerk"),
	Employee(2, "Mary", "Jackson", 40 , "hr", "manager"),
	Employee(5, "Tom",  "Bregg ", 30 , "it", "programmer"),
	Employee(1, "Dan", "Root", 45 , "it", "manager"),
	Employee(4, "Sally", "Robesrtson", 33 , "hr", "recruiter")
	};
	std::sort(std::begin(employeeList), std::end(employeeList), EmployeeComparator());

	cout << "Sorted Array " << endl;
	for (size_t i = 0; i != 5; ++i)
		cout << employeeList[i] << " ";
}
Жалуется на return a.getEmployeeId < b.getEmployeeId; , говорит

1>project1.cpp
1>d:\code\cs302\project1\project1\project1.cpp(14): error C3867: 'Employee::getEmployeeId': non-standard syntax; use '&' to create a pointer to member
1>d:\code\cs302\project1\project1\project1.cpp(14): error C2296: '<': illegal, left operand has type 'int (__thiscall Employee::* )(void) const'
1>d:\code\cs302\project1\project1\project1.cpp(14): error C2297: '<': illegal, right operand has type 'int (__thiscall Employee::* )(void) const'
1>Done building project "project1.vcxproj" -- FAILED.
https://www.youtube.com/watch?v=wOwblaKmyVw
User avatar
Medium-rare
Уже с Приветом
Posts: 9239
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: C++ для бегинеров

Post by Medium-rare »

Так эта... вызов функции?

Code: Select all

return a.getEmployeeId() < b.getEmployeeId();
Да не забудь тот метод-operator либо в public поставить, либо весь класс его сделай struct.
На тему.
... and even then it's rare that you'll be going there...
User avatar
Сабина
Уже с Приветом
Posts: 19045
Joined: 11 Jan 2012 09:25
Location: CA

Re: C++ для бегинеров

Post by Сабина »

Medium-rare wrote: 05 Feb 2018 03:49 Так эта... вызов функции?

Code: Select all

return a.getEmployeeId() < b.getEmployeeId();
Да не забудь тот метод-operator либо в public поставить, либо весь класс его сделай struct.
Ой... лучше вот это посмотри. Многовато всего. Лень, вечер воскресенья.
Если на функцию поправить - то еще хуже обругалось. На что непонятно, бо оператор и так паблик.
Ну и сама по себе идея что getter нельяз использовать в компараторе - это просто плевок в лицо общественности :mrgreen: . Два инстанса класса сравнивают как правило по какому то их его свойств.
Загадочный блин язык С++
https://www.youtube.com/watch?v=wOwblaKmyVw
User avatar
Prosche
Уже с Приветом
Posts: 7956
Joined: 08 Nov 2004 12:24
Location: GA

Re: C++ для бегинеров

Post by Prosche »

У вас в примере нет скобок, getEmployeeId функции. И паблик поставьте.
Last edited by Prosche on 05 Feb 2018 04:06, edited 1 time in total.
User avatar
Medium-rare
Уже с Приветом
Posts: 9239
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: C++ для бегинеров

Post by Medium-rare »

Сабина, уже лет пять усталые седые агрономы делают вот так с C++ 11 и лямбдой: https://stackoverflow.com/questions/512 ... h-a-lambda

Я без компилятора, ибо.

Code: Select all

std::sort(std::begin(employeeList), std::end(employeeList),
            [](const Employee& l, const Employee& r) -> bool {return l.getEmployeeId() < r.getEmployeeId();}
            );
Last edited by Medium-rare on 05 Feb 2018 04:18, edited 4 times in total.
... and even then it's rare that you'll be going there...
User avatar
Сабина
Уже с Приветом
Posts: 19045
Joined: 11 Jan 2012 09:25
Location: CA

Re: C++ для бегинеров

Post by Сабина »

Prosche wrote: 05 Feb 2018 04:05 У вас в примере нет скобок, getEmployeeId функции. И паблик поставьте.
Ой вы оба правы. Оказывается надо метод самого компаратора паблик обозвать и все.
Спасибо :fr:
https://www.youtube.com/watch?v=wOwblaKmyVw
User avatar
Сабина
Уже с Приветом
Posts: 19045
Joined: 11 Jan 2012 09:25
Location: CA

Re: C++ для бегинеров

Post by Сабина »

Еще надо доки сгенерировать каким то Doxygen
Это долгая история ? В студии можно как то быстро ?
https://www.youtube.com/watch?v=wOwblaKmyVw
User avatar
Medium-rare
Уже с Приветом
Posts: 9239
Joined: 04 Mar 2011 03:04
Location: SFBA

Re: C++ для бегинеров

Post by Medium-rare »

В VS никогда Doxygen не делал, а в Qt Creator не задумываясь, как тут: https://www.youtube.com/watch?v=KPN1y_vstjY
Сейчас уже и плаг-ина ставить не надо, как я понимаю, по умолчанию это есть.
... and even then it's rare that you'll be going there...
User avatar
AndreyT
Уже с Приветом
Posts: 3009
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: C++ для бегинеров

Post by AndreyT »

Сабина wrote: 05 Feb 2018 04:04 Если на функцию поправить - то еще хуже обругалось. На что непонятно, бо оператор и так паблик.
* Если вы перегрузили `operator <` для вашего класса, то нет необходимости писать для него еще и компаратор, сравнивающий по той же логике, что и `operator <`. Отдельный компаратор в такой ситуации можно написать для того, чтобы реализовать какую-то альтернативную логику сравнения. У вас же компаратор в точности повторяет логику `operator <`. Такой компаратор "не нужен" - `std::sort` без указания компаратора воспользуется уже определенным `operator <`.

Наличие такого компаратора - не ошибка. Но тем не менее он избыточен.

* Ваш `operator <` - функция с константными параметрами. У вас правый параметр оператора объявлен константным (ссылка на константу), а левый - нет. Это нехорошо. Если вы хотите перегружать `operator <` методом класса, то

Code: Select all

bool operator<(const Employee& e) const;
и далее

Code: Select all

bool Employee::operator < (const Employee& e) const {
  return employeeId < e.employeeId;
}
Отсутствие этого второго `const` может вылезти не сразу, но вылезет.

Однако когда речь идет о симметричных (с точки зрения типов параметров) операторах, то лучше реализовывать их отдельностоящими функциями, а не методами класса

Code: Select all

friend bool operator < (const Employee& a, const Employee& b) {
  return a.employeeId < b.employeeId;
}
* (Если уже вы хотите явный компаратор.) В компараторе, как уже было сказано, потеряны скобки при вызове функции и `public`. Опять же, сам оператор следует сделать `const`

Code: Select all

class EmployeeComparator
{
public:
	bool operator()(const Employee& a, const Employee& b) const
	{
		return a.getEmployeeId() < b.getEmployeeId();
	}
};
Однако, сделав вышеописанные исправления для `operator <`, вы можете просто воспользоваться уже определенным вами `operator <` для реализации компаратора. (Да и использовав `struct` вместо `class`, можно будет сэкономить строчку с `public`)

Code: Select all

struct EmployeeComparator
{
	bool operator()(const Employee& a, const Employee& b) const
	{
		return a < b;
	}
};
Last edited by AndreyT on 05 Feb 2018 18:38, edited 7 times in total.
Best regards,
Андрей
User avatar
AndreyT
Уже с Приветом
Posts: 3009
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: C++ для бегинеров

Post by AndreyT »

Del
Best regards,
Андрей
Pantigalt
Уже с Приветом
Posts: 803
Joined: 24 Jan 2007 07:32
Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA

Re: C++ для бегинеров

Post by Pantigalt »

Сабина,

Немного оффтопика по коду.
https://en.wikipedia.org/wiki/Pragma_once

Хоть это и нестандартно но намного проще использовать.
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
Pantigalt
Уже с Приветом
Posts: 803
Joined: 24 Jan 2007 07:32
Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA

Re: C++ для бегинеров

Post by Pantigalt »

Medium-rare wrote: 05 Feb 2018 04:06 Сабина, уже лет пять усталые седые агрономы делают вот так с C++ 11 и лямбдой: https://stackoverflow.com/questions/512 ... h-a-lambda

Я без компилятора, ибо.

Code: Select all

std::sort(std::begin(employeeList), std::end(employeeList),
            [](const Employee& l, const Employee& r) -> bool {return l.getEmployeeId() < r.getEmployeeId();}
            );
Я бы сократил еще дальше используя новый синтаксис С++ 11: curly brackets, auto and range-based for loop.

Code: Select all

int main()
{
	Employee employeeList[] = {
		{3, "John", "Reed",25 , "accounting", "clerk"},
		{2, "Mary", "Jackson", 40 , "hr", "manager"},
		{5, "Tom",  "Bregg ", 30 , "it", "programmer"},
		{1, "Dan", "Root", 45 , "it", "manager"},
		{4, "Sally", "Robesrtson", 33 , "hr", "recruiter"}
	};

	std::sort(std::begin(employeeList), std::end(employeeList), [](const auto& a, const auto& b) { return a.getEmployeeId() < b.getEmployeeId(); });

	cout << "Sorted Array " << endl;
	for (const auto& emp: employeeList)
		cout << emp << " ";

    return 0;
}
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
User avatar
AndreyT
Уже с Приветом
Posts: 3009
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: C++ для бегинеров

Post by AndreyT »

Pantigalt wrote: 06 Feb 2018 19:55 Я бы сократил еще дальше используя новый синтаксис С++ 11: curly brackets, auto and range-based for loop.
Generic lambda (`auto` в параметрах лямбды) - это начиная только с C++14.
Best regards,
Андрей
User avatar
AndreyT
Уже с Приветом
Posts: 3009
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: C++ для бегинеров

Post by AndreyT »

Pantigalt wrote: 06 Feb 2018 19:14 Хоть это и нестандартно но намного проще использовать.
Никогда не знаешь, что она гарантирует, а что нет. `#pragma once` отказались стандартизовать именно потому, что задача определения идентичности файла по пути к нему в современных файловых системах в общем случае трудноразрешима. `#pragma once` прижилась в первую очередь как средство негарантированной оптимизации, используемой вместе с классическими include guards, а не вместо них.
Last edited by AndreyT on 06 Feb 2018 20:47, edited 1 time in total.
Best regards,
Андрей
Pantigalt
Уже с Приветом
Posts: 803
Joined: 24 Jan 2007 07:32
Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA

Re: C++ для бегинеров

Post by Pantigalt »

AndreyT wrote: 06 Feb 2018 20:38
Pantigalt wrote: 06 Feb 2018 19:55 Я бы сократил еще дальше используя новый синтаксис С++ 11: curly brackets, auto and range-based for loop.
Generic lambda (`auto` в параметрах лямбды) - это начиная только с C++14.
Спасибо за уточнение. Я неправильно выразился - имел ввиду новый синтаксис С++11 и выше. Конечно же С++14.
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
Pantigalt
Уже с Приветом
Posts: 803
Joined: 24 Jan 2007 07:32
Location: Сергели->Новосибирск->SFBA->Новосибирск->Москва->NY->SFBA

Re: C++ для бегинеров

Post by Pantigalt »

AndreyT wrote: 06 Feb 2018 20:41 `#pragma once` прижилась в первую очередь как средство негарантированной оптимизации, используемой вместе с классическими include guards, а не вместо них.
Как по вашему почему VS по умолчанию генерирует #pragma once но не генерирует классические include guards?
Пытаются избежать проблем с именами?
Спи быстрее, твоя подушка нужна другому. Copyright Зощенко
User avatar
AndreyT
Уже с Приветом
Posts: 3009
Joined: 14 Apr 2004 01:11
Location: SFBA (было: Минск, Беларусь)

Re: C++ для бегинеров

Post by AndreyT »

Pantigalt wrote: 06 Feb 2018 20:51
AndreyT wrote: 06 Feb 2018 20:41 `#pragma once` прижилась в первую очередь как средство негарантированной оптимизации, используемой вместе с классическими include guards, а не вместо них.
Как по вашему почему VS по умолчанию генерирует #pragma once но не генерирует классические include guards?
Этот вопрос надо задать авторам VS. Наверное они решили, что для среднестатистического проекта - сойдет.

Интересно было бы поэкспериментировать с VS и посмотреть, как его `#pragma once` будет работать с одним и тем же файлом, видимым через hard links/symbolic links.
Best regards,
Андрей
User avatar
Prosche
Уже с Приветом
Posts: 7956
Joined: 08 Nov 2004 12:24
Location: GA

Re: C++ для бегинеров

Post by Prosche »

AndreyT wrote: 06 Feb 2018 21:01
Pantigalt wrote: 06 Feb 2018 20:51
AndreyT wrote: 06 Feb 2018 20:41 `#pragma once` прижилась в первую очередь как средство негарантированной оптимизации, используемой вместе с классическими include guards, а не вместо них.
Как по вашему почему VS по умолчанию генерирует #pragma once но не генерирует классические include guards?
Этот вопрос надо задать авторам VS. Наверное они решили, что для среднестатистического проекта - сойдет.

Интересно было бы поэкспериментировать с VS и посмотреть, как его `#pragma once` будет работать с одним и тем же файлом, видимым через hard links/symbolic links.
Рукожо...ым у которых в рамках одного модуля инклюдится один и тот же хедер с разными путями так и надо. Прагма уанс рулит. :D
User avatar
Сабина
Уже с Приветом
Posts: 19045
Joined: 11 Jan 2012 09:25
Location: CA

Re: C++ для бегинеров

Post by Сабина »

Ого, скока у нас тут сиплюсовиков :)! А я тут закрутилась и не заходила, сорри.
Впрочем у нас второе задание прибыло - какие то ksmall , так что скоро буду багить :)
https://www.youtube.com/watch?v=wOwblaKmyVw

Return to “Вопросы и новости IT”