0

I was working on a class which will contain an array of objects of another class. But I'm not able to do so. Here is a simplified version of the code I'm trying to use. Can anyone help me work with it?

Why s cannot access its own data members?

Can anyone show the whole concept of how to deal with these kind of scenarios?

P.S - ONLY USE of FRIEND (class or function) keyword. Inheritance isn't allowed.

class Student{
private:
    int roll;
    char name1[15];
};

class Subject  {
private:
    Student s[10];
};

int main()
{
    Subject s1;
    s1.s[1].roll = 5; // trying to set roll of 1st student
    return 0;
}

I was expecting that value will be assigned, but it has the following error. Why it is so?

error: 'Student Subject::s [10]' is private`
error: 'int Student::roll' is private
error: 'Student Subject::s [10]' is private
error: 'int Student::roll' is private
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770

4 Answers4

3

Can anyone help me how work with it. why s cannot access it's own data members.

It sure can but the error you are seeing is the result of trying to access private members of Subject and Student in main.

main cannot access private members of Subject or Student. In order to allow main to access the member variables directly, you'll have to make the member variables public. The other option is to add public accessor and modifier functions corresponding to the private member variables.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
2

The student array is declared as a private member of the Subject class.

private members cannot be accessed outside of the class scope, which means you cannot access it from your main (or any other) function.

the first option for you is to declare this array as public member. the other one is to use getter/setter for that member which will get/modify this member

class Student
{
private:
    int roll;
    char name1[15];

public:
    char* getName(void)
    {
        return strdup(this->name1); 
    }

    void setRoll(int r)
    {
        this->roll = r;
    }
};

class Subject
{
private:
    Student s[10];

public:

    void setStudentRoll(int roll, char *s_name)
    {
        for (int i = 0; i < 10; i++)
        {
            if (strcmp(this->s[i].getName(), s_name) == 0)
            {
                this->s[i].setRoll(roll);
                break;
            }
        }
    }
};

keep in mind that in order to set the student's roll member (which is also declared as a private member), you will have the same problem.

stylo
  • 496
  • 4
  • 12
  • Did you try to set any students roll from inside `setStudenRoll()`? I think you will meet an obstacle. – Yunnosch Sep 20 '19 at 05:05
  • Walking through the s[] array comparing the names with the given name (of course the name member will need to be retrieve the same way) and calling set_roll (which will be defined in the student class to set its roll), worked for me :S – stylo Sep 20 '19 at 05:10
  • Please show that, especially the part where you write the private attribute of a different class without being a friend. Maybe the code you do not want to show here gets easier, when you keep in mind that OP seems happy to provide the index. – Yunnosch Sep 20 '19 at 05:11
  • if the index is provided I agree that it is much easier :). I walked through the student array and used strcmp to match the student's name (using getName for the student class), when match was made I then used setRoll (for the student class) to set the student's roll. – stylo Sep 20 '19 at 05:19
  • Please [edit] to provide that helpful additional information directly within your answer, instead of hiding it in a comment. – Yunnosch Sep 20 '19 at 05:20
  • Honestly, haven't thought that's the real issue here. I took it for granted since this is an example for a different problem. – stylo Sep 20 '19 at 05:30
  • 1
    Fair is fair, I did take the index for granted. :-) But be warned, there are users here who poke at little things like that in answers, in what is a deep review. If you get a downvote it will not be by me, but you might get one by those users. – Yunnosch Sep 20 '19 at 05:31
2

If you want to make an attribute private but still intend to allow it to be set, then the commonly used idiom is to create a "setter".

In this case, you need to do it twice, for each of your classes with private attributes that you nevertheless want to set.

class Student{
    public:
        void setroll(int newroll)
        {
            roll = newroll;
        }
    private:
        int roll;
        char name1[15];
};

class Subject  {
    public:
        void setstudentsroll(int newroll, int index)
        {
            /* a good setter would at this point check the index,
            to make sure it does not access beyond the array */
            s[index].setroll(newroll);
        }
    private:
        Student s[10];
};

int main()
{
    Subject s1;
    s1.setstudentsroll(5,1); // trying to set roll of 1st student
    return 0;
}

Using the friend keyword for this is possible for the inner case, where the accessing code is in a class that can be named. But, and I assume that this is the actual problem you are having, it does not help for allowing main() to do the setting.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • Let me know if you need the inner case solved by using `friend`. – Yunnosch Sep 20 '19 at 04:58
  • @RemyLebeau What is the advantage of that way of formatting code? – Yunnosch Sep 20 '19 at 05:14
  • @RemyLebeau Please be more careful with changing phrasings. – Yunnosch Sep 20 '19 at 05:16
  • @RemyLebeau By "that way of formatting" I mean the triple back tick instead of indenting by 4. I like your improved indentation, thanks for that. But please explain why you consider your choice of markdown an improvement worth editing. – Yunnosch Sep 20 '19 at 05:37
  • I frequently use a mobile device to access StackOverflow nowadays, and using the triple tick markup with tab chars for indenting is far easier to type on a touchscreen keyboard than using 4-space markup, which makes using tab chars for indenting a PITA because my keyboard likes to delete the 4-spaces when typing the tabs. Also, the triple tick markup is just cleaner particularly when specifying a syntax highlighting language – Remy Lebeau Sep 20 '19 at 06:52
0

You are declared the variable and student Object has an Private access specifier. you cann't initialize the variable values out side that class. using public you can initialize the variable anywhere on the program... Solution:

class Student{
 public:
 int roll;
 char name1[15];
 };
 class Subject  {
 public:
 Student s[10];
 };
 int main()
 {
  Subject s1;
  s1.s[1].roll = 5; // trying to set roll of 1st student 
 return 0;
 }
AravindK
  • 151
  • 8