none
Не получается "функции-другу" получить доступ к закрытым данным класса RRS feed

  • Вопрос

  • Язык: C++

    Есть три класса:

    1. Voting, который содержит несколько закрытых переменных.
    2. Citiz - содержит функцию, которая является другом для Voting.
    3. Cec - весь класс друг Voting.

    Проблема: не получается получить доступ к закрытым элементам Voting из функции класса Citiz, хотя она объявлена как "друг". При этом все функции Cec имеют доступ ко всем элементам Voting, так как весь класс Cec есть друг Voting.

    Проблема возникает в void Citiz::vote(Voting *list, int num): 

    Ошибка 2 error C2248: Voting::fir: невозможно обратиться к private член, объявленному в классе "Voting" c:\users\tipo\documents\exploring\cpp\cpp_upr_5_5\cpp_upr_5_5\main.cpp 54 1 cpp_upr_5_5


    В чём моя ошибка(код ниже)?

    Заранее спасибо!

    #include <iostream>
    
    using namespace std;
    
    class Citiz;
    class Cec;
    
    class Voting {
    public:
    	void init(void);
    	friend void Citiz::vote(Voting *list, int num);
    	friend Cec;
    private:
    	int fir;
    	int sec;
    	int thir;
    	int total;
    	int leave;
    };
    
    class Citiz {
    public:
    	void vote(Voting *list, int num);
    };
    
    class Cec {
    public:
    	void readData(Voting list);
    	void cleanData(Voting *list);
    };
    
    int main(void)
    {
    	Voting year;
    	Citiz man;
    	Cec chur;
    
    	year.init();
    	man.vote(&year, 2);
    	chur.readData(year);
    	chur.cleanData(&year);
    }
    
    void Voting::init(void)
    {
    	fir = sec = thir = 0;
    	total = leave = 0;
    }
    
    void Citiz::vote(Voting *list, int num) //Здесь возникает ошибка!
    {
    	switch (num) {
    	case 1:
    		list->fir++;
    		break;
    	case 2:
    		list->sec++;
    		break;
    	case 3:
    		list->thir++;
    		break;
    	default:
    		list->leave++;
    		break;
    	}
    	list->total++;
    }
    
    void Cec::readData(Voting list)
    {
    	cout
    		<< list.fir << endl
    		<< list.sec << endl
    		<< list.thir << endl
    		<< list.leave << endl
    		<< list.total << endl;
    }
    
    void Cec::cleanData(Voting *list)
    {
    	list->fir = 0;
    	list->sec = 0;
    	list->thir = 0;
    	list->leave = 0;
    	list->total = 0;
    }



    • Изменено iTiPo 12 марта 2014 г. 17:42
    12 марта 2014 г. 17:42

Ответы

  • Если Вы ссылаетесь на метод класса, то класс должен быть объявлен выше по тексту:

    class Voting;
    
    class Citiz
    {
        ...
    };
    
    class Voting
    {
        ...
    };
    


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    • Помечено в качестве ответа iTiPo 13 марта 2014 г. 9:25
    • Снята пометка об ответе iTiPo 13 марта 2014 г. 11:00
    • Помечено в качестве ответа iTiPo 13 марта 2014 г. 11:01
    12 марта 2014 г. 20:33

Все ответы

  • Если Вы ссылаетесь на метод класса, то класс должен быть объявлен выше по тексту:

    class Voting;
    
    class Citiz
    {
        ...
    };
    
    class Voting
    {
        ...
    };
    


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    • Помечено в качестве ответа iTiPo 13 марта 2014 г. 9:25
    • Снята пометка об ответе iTiPo 13 марта 2014 г. 11:00
    • Помечено в качестве ответа iTiPo 13 марта 2014 г. 11:01
    12 марта 2014 г. 20:33
  • Спасибо большое! 

    Теперь всё компилируется без ошибок. Но почему в IDE фрагменты кода, которые ранее вызывали ошибку теперь подсвечиваются красной линией, при наведении на которую выводится такое же предупреждение? Однако компиляция проходит без проблем.

    13 марта 2014 г. 4:10
  • Кстати, почему мой вариант объявления классов не подошёл? 
    13 марта 2014 г. 4:11
  • Вот исправленный код. Никаких подчеркиваний у меня нет.

    #include <iostream>
    
    using namespace std;
    
    class Voting;
    class Cec;
    
    class Citiz {
    public:
    	void vote(Voting *list, int num);
    };
    
    class Voting {
    public:
    	void init(void);
    	friend void Citiz::vote(Voting *list, int num);
    	friend Cec;
    private:
    	int fir;
    	int sec;
    	int thir;
    	int total;
    	int leave;
    };
    
    class Cec {
    public:
    	void readData(Voting list);
    	void cleanData(Voting *list);
    };
    
    int main(void)
    {
    	Voting year;
    	Citiz man;
    	Cec chur;
    
    	year.init();
    	man.vote(&year, 2);
    	chur.readData(year);
    	chur.cleanData(&year);
    }
    
    void Voting::init(void)
    {
    	fir = sec = thir = 0;
    	total = leave = 0;
    }
    
    void Citiz::vote(Voting *list, int num) //Здесь возникает ошибка!
    {
    	switch (num) {
    	case 1:
    		list->fir++;
    		break;
    	case 2:
    		list->sec++;
    		break;
    	case 3:
    		list->thir++;
    		break;
    	default:
    		list->leave++;
    		break;
    	}
    	list->total++;
    }
    
    void Cec::readData(Voting list)
    {
    	cout
    		<< list.fir << endl
    		<< list.sec << endl
    		<< list.thir << endl
    		<< list.leave << endl
    		<< list.total << endl;
    }
    
    void Cec::cleanData(Voting *list)
    {
    	list->fir = 0;
    	list->sec = 0;
    	list->thir = 0;
    	list->leave = 0;
    	list->total = 0;
    }
    


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    13 марта 2014 г. 6:31
  • Кстати, почему мой вариант объявления классов не подошёл? 

    Потому что предварительное объявление класса в виде

    class A;

    годится только для использования имени типа (A) в объявлении указателя (A*). А вот чтобы создавать объекты класса, а уж, тем более, вызывать методы, предварительное полное объявление самого класса просто необходимо!


    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    13 марта 2014 г. 6:39
  • Спасибо большое за пояснения! 
    13 марта 2014 г. 9:25