• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Brak dostępu do atrybutu klasy w funkcji zaprzyjaźnionej - dlaczego?

Object Storage Arubacloud
0 głosów
121 wizyt
pytanie zadane 23 lipca 2020 w C i C++ przez maks0410 Początkujący (290 p.)

Witam wszystkich,

mam następujący problem. Chciałem zrobić zadanie z odc. 4 kursu obiektowego C++ Pana Zelenta, jednak w oddzielnych plikach dla każdej klasy. Niestety, nie mogę uzyskać dostępu do atrybutów klasy punkt, a do atrybutów klasy prostokąt tak, pomimo identycznego kodu (w obydwu klasach zadeklarowałem przyjaźń z użytą funkcją). Czy ktoś mógłby mi wytłumaczyć dlaczego tak się dzieje? Dodam, że po zmienieniu atrybutów na "public" wszystko działa jak powinno, więc problem na pewno leży w hermetyzacji danych.

Załączam same pliki nagłówkowe, bo myślę, że tutaj będzie widoczny ten problem.

#pragma once
#include <iostream>
#include "Punkt.h"

class Prostakat
{
	int x, y, height, width;
	std::string name;

public:
	Prostakat(std::string = "Prostakat", int = 0, int = 0, int = 1, int = 1);
	void load();
	void show();
	friend void hit(Punkt pkt, Prostakat p);
};
#pragma once
#include <iostream>
#include "Prostakat.h"

class Punkt
{
	int x, y;
	std::string name;

public:
	Punkt(std::string = "Punkt", int = 0, int = 0);
	void load();
	void show();
	friend void hit(Punkt pkt, Prostakat p);
};

Tak wyglądają klasy, a w następującej funkcji nie mogę się odwołać do atrybutów punktu:

void hit(Punkt pkt, Prostakat p)
{
    if ((pkt.x >= p.x) && (pkt.x <= p.x + p.width) && (pkt.y >= p.y) && (pkt.y <= p.y + p.height))
        std::cout << "TAK!";
    else
        std::cout << "NIE!";
}

Z góry dziękuję za pomoc :)

2 odpowiedzi

+1 głos
odpowiedź 24 lipca 2020 przez maks0410 Początkujący (290 p.)

Znalazłem rozwiązanie problemu (co prawda kolega znalazł laugh), jednak wciąż prosiłbym o wytłumaczenie. Problem rozwiązuje się, jeżeli przed deklaracją klasy Punkt w pliku Punkt.h zadeklaruję klasę Prostokat, w następujący sposób:

#pragma once
#include <iostream>
#include "Prostakat.h"

class Prostakat;

class Punkt
{
	int x, y;
	std::string name;

public:
	Punkt(std::string = "Punkt", int = 0, int = 0);
	void load();
	void show();
	friend void hit(Punkt pkt, Prostakat p);
};

Jeżeli klasy byłyby w jednym pliku, a klasa Punkt zadeklarowana przed klasą Prostokat, to rozumiem potrzebę deklaracji tej klasy - w końcu void hit jej używa, więc musi wiedzieć że taka klasa istnieje. Jednak w sytuacji, gdzie używam dwóch oddzielnych plików z klasami, myślałem że:

a) zainkludowanie potrzebnego pliku nagłówkowego "Prostakat.h" sprawi, że klasa jest już znana, lub

b) konieczna będzie deklaracja klasy Punkt również w klasie Prostakat, a tak nie jest - ta klasa działa bezproblemowo.

Nie ukrywam więc, że fajnie byłoby to zrozumieć, bo teraz już całkiem się pogubiłem. Chociaż kod oczywiście działa.

3
komentarz 24 lipca 2020 przez adrian17 Ekspert (344,860 p.)

Jednak w sytuacji, gdzie używam dwóch oddzielnych plików z klasami

Masz zapętlone include'y. Punkt.h załącza Prostokąt.h załącza Punkt.h, ale ostatni się nie dzieje przez include guard. Zamiast tego, trzeba zrobić foward declaration typu.

(a uwaga mocno na boku: mam nadzieję że to analiza czysto teoretyczna, bo w praktyce używanie `friend` do czegokolwiek jest mocno odradzane.)

komentarz 24 lipca 2020 przez maks0410 Początkujący (290 p.)

Bardzo dziękuję, teraz już rozumiem, nie wiedziałem o tych mechanizmach smiley

0 głosów
odpowiedź 23 lipca 2020 przez Michałełe Nałogowiec (25,600 p.)
Hej, przepisałem Twój kod i kompiluje mi się bez błędów - jakie dokładnie dostajesz błąd?
komentarz 23 lipca 2020 przez maks0410 Początkujący (290 p.)

W funkcji void hit(Punkt pkt, Prostakat p) w mainie nie mogę się dostać do żadnego atrybutu pkt, takich jak pkt.x lub pkt.y, więc błąd typu "member Punkt::x is inaccessible".

Jeśli kompiluje się dobrze, to może jednak błąd w plikach .cpp? Dołożę je w takiej sytuacji:

#include "Prostakat.h"
#include <iostream>

Prostakat::Prostakat(std::string n, int xx, int yy, int h, int w)
{
	name = n;
	x = xx;
	y = yy;
	height = h;
	width = w;
}

void Prostakat::load()
{
	std::cout << "Podaj nazwe prostakata: ";
	std::cin >> name;
	std::cout << "Podaj wspolrzedna X punktu lewgo dolnego wierzcholka: ";
	std::cin >> x;
	std::cout << "Podaj wsporzedna Y punktu lewgo dolnego wierzcholka: ";
	std::cin >> y;
	std::cout << "Podaj szerokosc prostakata: ";
	std::cin >> width;
	std::cout << "Podaj wysokosc prostakata: ";
	std::cin >> height;
}

void Prostakat::show()
{
	std::cout << "Nazwa prostkata: " << name << std::endl;
	std::cout << "Wspolrzedne lewego dolnego wierzcholka: (" << x << " , " << y << ")";
	std::cout << "Wysokosc: " << height;
	std::cout << "Szerokosc: " << width;
}
#include "Punkt.h"
#include <iostream>

Punkt::Punkt(std::string n, int xx, int yy)
{
	name = n;
	x = xx;
	y = yy;
}

void Punkt::load()
{
	std::cout << "Podaj nazwe punktu: ";
	std::cin >> name;
	std::cout << "Podaj wspolrzedna X: ";
	std::cin >> x;
	std::cout << "Podaj wsporzedna Y: ";
	std::cin >> y;
}

void Punkt::show()
{
	std::cout << "Nazwa punktu: " << name << std::endl;
	std::cout << "Wspolrzedne punktu: (" << x << " , " << y << ")";
}

 

komentarz 24 lipca 2020 przez Piotr Batko Stary wyjadacz (13,190 p.)
No nie możesz się do tego dobrać z maina, bo się z mainem nie zaprzyjaźniłeś. Zaprzyjaźniłeś się z funkcją hit. Więc hit ma dostęp, a main nie :)
komentarz 24 lipca 2020 przez maks0410 Początkujący (290 p.)
Tylko, że problem pojawia się już w momencie deklaracji funkcji, a nie jej wywołania w mainie (Visual Studio podkreśla te zmienne w ciele funkcji). Spróbowałem jednak, wciąż nic to nie daje.

Podobne pytania

0 głosów
3 odpowiedzi 286 wizyt
pytanie zadane 20 sierpnia 2015 w C i C++ przez Jonki Dyskutant (8,180 p.)
+1 głos
1 odpowiedź 268 wizyt
0 głosów
0 odpowiedzi 176 wizyt

92,580 zapytań

141,433 odpowiedzi

319,665 komentarzy

61,965 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...