Heroes of C++ assemble!: Questions about Classes

Pages: 12
Hi!

I'm learning Programming and I'm very new so I'd like to borrow your wast network of knowledge on Classes.

I have looked at a good few post on this forum but I learn better when I get to ask my own questions to tailor an answer I can best learn from.

I'm taking a non-attending class on C++ but the material which I'm given is appallingly bad and often ask the reader to find stuff out on your own... a great way of learning I admit but not when I'm unable to interpret that which I'm seeing(not to mention the best info is all in English and the language barrier when it comes to technical stuff makes it worse <-I'm Swedish).

so here goes a few questions about Classes!(This is probably like watching a blind man drive for you guys so try to me modest when pointing out my idiocy):

Constructors:
Is there any scenario where a constructor would be a downside or is the common practice to always have one?

Closing braces:
I think having all objects within the class rather than defining them outside makes it a lot easier to spot where the belong (even though they have the class name in front e.g Class::constructor)

what is the common practice any downsides?

for example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>


class Person{
    public:
        std::string name;
        int age;
        
    Person(std::string _name, int _age){
        name=_name;
        age=_age;
    }

    void Print(){
        std::cout<<name<<age;
    }
};
int main(){

    Person pers("Johan",23);
    pers.Print();
          
}


VS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>


class Person{
    public:
        std::string name;
        int age;
        void Print();
        Person(std::string, int);
};

    Person::Person(std::string _name, int _age){
        name=_name;
        age=_age;
};

    void Person::Print(){
        std::cout<<name<<age;
};
int main(){

    Person pers("Johan",23);
    pers.Print();
         
}


I would like to ask more about uniform initialization but I have not seen the need for it yet or done enough research so maybe later.

That's all I have for now I don't know enough to pose any more questions but if you come to think of something else very important about classes and objects or something worth knowing, post it as well!

thanks!
Is there any scenario where a constructor would be a downside or is the common practice to always have one?
Any class has constructors: even if you do not define any, compiler will generate default, copy and move constructors. You can explicitely delete them, but if class does not have any constructors, you cannot create an object of this class, nor you can use it as base. Which is not helpful.

Closing braces:
I think having all objects within the class rather than defining them outside makes it a lot easier to spot where the belong (even though they have the class name in front e.g Class::constructor)

what is the common practice any downsides?
Open standard library header <string>. Find implementation of string itself. Try to find how many ways to search something in string exist.

That is why it is common to define member functions outside of class: to have class definition lightweight, self-documenting and easy to comprehend. There are cases when you have to define them outside of class too.
First of all, good luck on your learning! This is a great site to learn programming in general, and C++ in particular.

My answers to your questions:
Constructors:
Is there any scenario where a constructor would be a downside or is the common practice to always have one?


The only downside I can think of is when a programmer has a very poorly-written class. You will always have a constructor: The compiler demands it. Therefore, if your class has only one way to instantiate that class, make sure any automatically-added classes can't hurt you. You can do this by making a default constructor private, so that it is not possible to be called.


Closing braces:
I think having all objects within the class rather than defining them outside makes it a lot easier to spot where the belong (even though they have the class name in front e.g Class::constructor)

what is the common practice any downsides?


In either of your cases, you have written a class that is not portable (your main function)! You should either put everything in the class header, or create a source file and a header file.

Now, as far as having the class in just the header verses a source file and a header file, it is up to the programmer. One reason for putting everything in the header is that all another programmer needs to do is to write:

#include "your_class.h"

Thanks for the replies!

So to define the objects straight away e.g: Person.age=22; Person.name="Johan"
isn't used much?

And going by my examples is the second code the more common way or is it only for member functions you define it outside the class(normally)?

Like I said I like the first one as (for me) it's easier to see what goes in to the class(especially when in codeblocks you can minimize the entire class rather than each part at the time)and it's a little bit less code.
but I suspected there might be a reason why you'd do Person::Person rather than having it inside the class... if anyone care to elaborate further why this is a poor idea I'm happy to listen.

Also as of now I'm only working with the main file having all code above the main function and calling it there. So I'm not using and headers even though I see why it would improve readability considerably when implementing lots of classes.
When handing in my assignment it's usually specified to be in the same cpp file too so I'd just have to move it all back in there later.

thanks for the replies keep em coming, I need to understand why I do something and not just get told to do it or I won't learn!

In any large project you want your declaration of the class to be separated from the implementation of the functions. Think about having a couple of functions, each with a few hundred lines of code. You class declaration would be almost impossible to read. If you have a large project, it is better to have the implementations for the class functions in a cpp file. This is done to increase the speed of the compilation. Say you have 100 files, all including "person.h". Now if you make a small change in Person::Print(), such as to put a space between name and age, you don't change the class definition, only the implementation. If the implementation is in the same file (either inside or outside the class definition), all 100 files need to be recompiled. If the implementation is in a separate file (say person.cpp), only that particular file needs to be compiled.
So to define the objects straight away e.g: Person.age=22; Person.name="Johan"
isn't used much?
It is used for behaviorles aggregates. In proper classes it breaks encapsulation and is not used.

there might be a reason why you'd do Person::Person rather than having it inside the class
class 1 has pointer to class 2 and calls some member function of it.
class 2 has pointer to class 1 and calls some member functions.
Now you have to define member function outside of class, or you won't be able to break circular dependency.
okey new question!

if I have a constructor:

1
2
3
4
Person::Person(std::string keyName, int keyAge){
    name=keyName;
    age=keyAge;
}


how would I pass my value in to an array?

for example I could:

1
2
3
4
5
6
7
8
9
10
11
12
void Person::Info(std::string keyName, int keyAge){
    namn=keyName;
    alder=keyAge;
};

int main(){
 Person p[4];
    p[0].Info("Karolina",21);
    p[1].Info("Chuck Norris",9000);
    p[2].Info("Bad Luck Brian",18);
    p[3].Info("Johan",23);
}


and that could later be printed but if I had a constructor I couldn't do
1
2
Person p[4];
p[0].Person("a",1);

so how would I pass the values in to the array?

This code is part of a linear search function I'm tasked to do and I need both:

a method called Print that would print name and age with a constructor:
e.g
1
2
3
4
5
6
7
8
9
void Person::Print(){
        std::cout<<name<<age;

int main(){
Person pers("Johan",23);
    pers.Print();

return 0;
}


and the linear search function with the array but I'm to inexperienced to understand how I could either have both the Person::info without having the compiler whine about which to use or how to pass values from my constructor straight in to the array in the same way info works. Alternatively how would I pass the values from ::Info in to my method Print without my constructor?

(There's obviously a lot of code missing in my examples but I hope they'll get the message through)

I work 8 hours and study 8 hours every day so at 1am the answer could be staring me in the face and I could miss it but I could learn something from asking anyway!

and please start from the very very basics and point out any oddities you might see as it's the best way I'll learn... my code may be running but if it's not useful later on I'm not doing me any favours.

if you need the rest of the code I could print it aswell just ask
Use list initialization + uniform initialization for your array:

Person p[4] {{"Karolina",21}, {"Chuck Norris",9000}, {"Bad Luck Brian",18}, {"Johan",23}};
You my friend is just magic!

I was trying to initialize my array like that earlier but could not figure out how 2 values would go in to each index in a list(I missed the braces around all the other braces)

now the magic part is that:

1
2
3
4
void Person::Info(std::string keyName, int keyAge){
    namn=keyName;
    alder=keyAge;
};


suddenly became completely redundant.

This poses a whole lot of questions though so for the sake of learning i'll be making some questions and some assumptions:

1: Person::info is no longer needed because the entire array is referring to Person where name and age is already stored?
2: functional and uniform initialization is the same but look different?
Q1: why can I refer the array to "Person" in a list but not as "Person p[0]("Karolina,21)" to avoid passing values with a method?


This is the code so far:
I have yet to make it look "Pretty", there's hardly any documentation and the variables are a mix of swedish and english so don't mind the poor quality I will tidy up later when everything works the way I want it.

(SkrivUt=Print is one of the prerequisites of the assignment but I'm not sure why as I can already print from the array. )

The next step in the assignment is the beloved bubblesort.....honestly this book feels like learning to drive without anyone telling you about traffic laws I constantly have to re-learn things the community tells me is retarded.

Also I apologize if my terminology is completely wrong as swedish->english isn't always a straight line so to speak.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <string>

class Person{
    public:
        std::string namn;
        int alder;
        void SkrivUt();
        Person(std::string,int);

};

Person::Person(std::string keyName, int keyAge){
    namn=keyName;
    alder=keyAge;
};


void Person::SkrivUt(){
        std::cout<<namn<<", "<<alder<<"\n";
};


//linear search function. Person pointer för att sedan ge persArray vädet myList
int LinearSearch(Person* persArray,int n,int key){
    for(int i = 0;i<n;i++){
        if(persArray[i].alder==key){
            return i;
        }
    }
    return -1;
};
int main(){
    
    Person pers("Johan",23);
    pers.SkrivUt();
    
    
    //values of array
    Person p[4] = {{"karolina",21},{"Chuck Norris",9000},{"Bad Luck Brian",18},{"Johan",23}};
    



    //call function, assign value, assign key
    int index=LinearSearch(p,4,23);


    if(index==-1){
        std::cout<<"person not found";
    }   else{
            std::cout<<p[index].namn<<" can be found on index "<<index;
         }




    return 0;
}
1: Person::info is no longer needed because the entire array is referring to Person where name and age is already stored?
It is not needed anymore, but you still can have it if you want to.

Q1: why can I refer the array to "Person" in a list but not as "Person p[0]("Karolina,21)" to avoid passing values with a method?
In Person p[0]("Karolina,21) you are trying to invoke operator() on your class. You cannot call constructor as all array objects are already initialized: you can only pass parameters to constructor when variable is declared
I'd hate to make a new thread so I'll continue to post here as it regards the same project only more issues!

long story short my exercises are:

1:make a class(Person) with string name and int age and a method(Print)
2:make a linear search function that searches and array(name and age) in class Person
(example given: int LinearSearch(Person p[],int n,int a))
3:make a sorting function using bubblesort that sorts an array(name and age) in class Person
(example given: void BubbleSort(Person p[],int n))

it says send in all solutions in the same cpp file and class Person should be used in all of them which makes it trickier(or I could have tried to create more classes in headers and call them in main)

this is what I've got:(most comments removed and some variables had their name changed as they were in swedish so I hope I didn't break anything while translating)

My problems are:
1:can't use a pointer in my sorting function like I did in search(would like to know why)
2:can't make an array in class Person that can be sorted using my function(see pre-exisiting array "familj"
3: can't sort string due to conversion issues I don't understand

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <string>


class Person{
    public:
        std::string name;
        int age;
        void Print();
        Person(std::string,int);
        int temp;      
};
//constructor
Person::Person(std::string keyName, int keyAge){
    name=keyName;
    age=keyAge;
};

void Person::Print(){
        std::cout<<name<<", "<<age<<"\n";
};


int LinearSearch(Person* persArray,int n,int key){
    for(int i = 0;i<n;i++){
        if(persArray[i].age==key){
            return i;
        }
    }
    return -1;
};
//I tried using a pointer like in the search function but that gives errors and I don't understand why
int SortArray(int tempArray[], int n){ 
    for(int i =0 ;i<n;i++){
        int nrLeft=n-i;
    
         for(int j = 0 ;j<nrLeft;j++){
            
             if (tempArray[j]<tempArray[j-1]){
                 int temp = tempArray[j];
                 tempArray[j]=tempArray[j-1];
                 tempArray[j-1]=temp;
             }
         }
    }
    
    
    for(int i=0;i<n;i++){
        std::cout<<tempArray[i]<<std::endl;
    }
    return 0;    
};
int main(){
    
    //Print
    Person pers("Johan",23);
    pers.Print();
    
    
    //array for searching
    Person p[4] {{"karolina",21},{"Chuck Norris",9000},{"Bad Luck Brian",18},{"Johan",23}};

/* This is the array I'd like sorted
    Person familj[4] {{"karolina",21},{"Chuck Norris",9000},{"Bad Luck Brian",18},{"Johan",23}};*/
    


    
    int index=LinearSearch(p,4,23);
   


    if(index==-1){
        std::cout<<"person not found";
    }   else{
            std::cout<<p[index].name<<" can be found on index "<<index<<std::endl;
    }

    //function works but I can't create an array in class Person without errors nor sort string"
    int familj[4] {21,9000,18,23};
    int sort=SortArray(familj,4);


    return 0;
};
Last edited on
1:can't use a pointer in my sorting function like I did in search(would like to know why)
You are using pointers. int tempArray[] is same as int* tempArray.

2:can't make an array in class Person that can be sorted using my function(see pre-exisiting array "familj"
You need to overload operator< for your class so it would know how you need to sort it.

3: can't sort string due to conversion issues I don't understand
Can you give an example
EDIT: I'm retarded....Dawned me I probably shouldn't sort the entire array just the age in the array like in the search function and there we had it!

Now I have a new Problem that the Names do not get sorted along with the age like I'd hoped.
and I'm seeing the wrong output will have to investigate further and see if I can solve it
Last edited on
the Names do not get sorted along with the age like I'd hoped
Do you just swap ages but not names?
yes that would be the problem

I had hoped if index 1 got sorted to position 2 then all values index 1 held would be printed in position 2 as my function does not accept string.

 error: cannot convert 'std::string {aka std::basic_string<char>}' to 'int' in initialization


so some way to assign my names the same value as the age they're given but it has to work if I decide to change age in the array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <string>


class Person{
    public:
        std::string name;
        int age;
        void Print();
        Person(std::string,int);
        int temp;
        std::string arName; 
        int arAge;
        Person();
        
};
//constructor
Person::Person(std::string keyName, int keyAge){
    name=keyName;
    age=keyAge;
};
//default constructor
Person::Person(){
    arName="Johan";
    arAge=23;
};
//Print method
void Person::Print(){
        std::cout<<arName<<", "<<arAge<<"\n";
};

//search function
int LinearSearch(Person* persArray,int n,int key){
    for(int i = 0;i<n;i++){
        if(persArray[i].age==key){
            return i;
        }
    }
    return -1;
};

//sort function
int SortArray(Person* persArray, int n){ 
    for(int i =0 ;i<n;i++){
        int nrLeft=n-i;
    
         for(int j = 0 ;j<nrLeft;j++){
            
             if (persArray[j].age<persArray[j-1].age){
                 int temp = persArray[j].age;
                 persArray[j].age=persArray[j-1].age;
                 persArray[j-1].age=temp;
             }
         }
    }
    
    
    for(int i=0;i<n;i++){
        std::cout<<persArray[i].age<<", "<<persArray[i].name<<std::endl;
    }
     return 0;   
};
int main(){
    
    //Print default constructur
    Person pers;
    pers.Print();
    
    
    //array p
    Person p[4] {{"karolina",21},{"Chuck Norris",25},{"Bad Luck Brian",23},{"Johan",22}};
    int sort=SortArray(p,4);
    int index=LinearSearch(p,5,23);
   
    if(index==-1){
        std::cout<<"person not found";
    }   else{
            std::cout<<p[index].name<<" can be found on index "<<index<<std::endl;
    }

  
    return 0;
};
Swap whole entries, not just some submembers.

YOur inner loop body should look roughtly like:

1
2
if( NeedSwapping )
    SwapWholePersons


error: cannot convert 'std::string {aka std::basic_string<char>}' to 'int' in initialization
You are trying to assign string to int. This is wrong too actually. You need to swap Persons as whole struct, not parts of it.
as a complete noob(and I hate to ask for answers as I'm less likely to learn)

how would I swamp whole entries? so far I can only get it to work if I swap .age as pointed out my function won't do string.

if I remove .age and try to swamp the whole array(persArray[j]) I get:

 In function 'int SortArray(Person*, int)':
48:30: error: no match for 'operator<' (operand types are 'Person' and 'Person')
49:40: error: cannot convert 'Person' to 'int' in initialization
51:32: error: no match for 'operator=' (operand types are 'Person' and 'int')
51:32: note: candidates are:
5:7: note: Person& Person::operator=(const Person&)
5:7: note:   no known conversion for argument 1 from 'int' to 'const Person&'
5:7: note: Person& Person::operator=(Person&&)
5:7: note:   no known conversion for argument 1 from 'int' to 'Person&&'
 In function 'int main()':
no match for 'operator<' (operand types are 'Person' and 'Person')
Comparison part may stay the same. It has no relation to the swapping. Or you can actually create operator< for your class.
cannot convert 'Person' to 'int' in initialization
I assume problem is with this line: int temp = persArray[j]. Why there is int here? Why did you place it here in first place?
what does create operator< mean? should I overload it? and how?
(this is supposed to be an intro to classes so I havn't worked with any of it before)

I had to declare temp somehow but there's nothing that takes both numbers and string is there? what would auto do?
nothing that takes both numbers and string is there?
THere actually is. What your array holds? Which type?

what does create operator< mean?
http://www.learncpp.com/cpp-tutorial/91-introduction-to-operator-overloading/
http://www.learncpp.com/cpp-tutorial/94-overloading-the-comparison-operators/

should I overload it?
In your case, no. Just stick with your previous version: if (persArray[j].age<persArray[j-1].age){
Pages: 12