Странная ошибка при компиляции Dev-c++

316
26 ноября 2016, 18:59

Добрый день! Пишу простой класс на C++ при компиляции наткнулся на вот такую вот странную проблему.. Я мало что разбираю в C++, но вот мой .h и .cpp файлы:

Если есть ошибки в правописании кода, прошу оставлять на будущее заметки типа: так нельзя писать в C++, а надо вот так...

Student.cpp

#include "Student.h"
#include <string>
using std::string;
Student::Student(){}
void Student::setName(string n){
    name = n;
}
void Student::setSurname(string s){
    surname = s;
}
void Student::setAge(int a){
    age = a;
}
void Student::setCourse(int c) {
    course = c;
}
void Student::setGroup(string g){
    group = g;
}
void Student::setMarks(string* mark){
    marks = mark;
}
string Student::getName(){
    return name;
}
string Student::getSurname(){
    return surname;
}
int Student::getAge(){
    return age;
}
int Student::getCourse(){
    return course;
}
string Student::getGroup(){
    return group;
}
string* Student::getMarks(){
    return marks;
} 

Student.h

#ifndef Student_h
#define Student_h
#include <string>
using std::string;
class Student{
    public:
        Student();
        void setName(string);
        string getName();
        void setSurname(string);
        string getSurname();
        void setAge(int);
        int getAge();
        void setCourse(int);
        int getCourse();
        void setGroup(string);
        string getGroup();
        void setMarks(string*);
        string* getMarks();
    private:
        string name;
        string surname;
        int age;
        int course;
        string group;
        string* marks;
};
#endif

Main.cpp

#include <stdio.h>
#include <iostream>
#include "Student.h"
using std::cout;
using std::endl;
int main(){
    Student test;
    string marks[] = {"B","B","C","A","A","A"};
    test.setName("Name");
    test.setSurname("Surname");
    test.setAge(100);
    test.setCourse(100);
    test.setGroup("606.4");
    test.setMarks(marks);
    cout << test.getName() << endl;
    cout << test.getSurname() << endl;
    cout << test.getAge() << endl;
    cout << test.getCourse() << endl;
    cout << test.getGroup() << endl;
    string* mark = test.getMarks();
    for(int i = 0 ; i < 6 ; i++){
        cout << mark[i] <<" ";
    }
}

Вроде все правильно делаю, но странная ошибка при компиляции происходит...

Это при компиляции Main.cpp

А это при компиляции Student.cpp

Подскажите где все мои грубые ошибки?

Answer 1

Насчет того, почему не компилируется - как уже писали, ваши ошибки - ошибки линковки, так что это неподключенный к проекту файл Student.cpp, а ненайденная WinMain говорит о том, что вы пытаетесь создавать оконное приложение, а не консольное.

Но у вас есть и вторая часть вопроса - как писать. У вас нет ошибок - в том смысле, что они вызовут неработоспособность программы. Но, примерно как вы и сформулировали - так писать на C++ не стоит...

Я бы начал с того, что у вас по сути не класс, а структура. В том смысле, что ваш класс не содержит какого-то специфичного внутреннего состояния, которое следовало бы обязательно поддерживать в согласованном состоянии, или какой-то иной функциональности, кроме установки и возврата полей. Поэтому лично я не вижу большого греха в том, чтобы просто объявить ваш класс структурой (т.е. классом со всеми открытыми членами) и работать прямо с ними:

struct Student{
    string name;
    string surname;
    int age;
    int course;
    string group;
    string* marks;
};
...
Student test;
test.name = "Name";

Если же планируется какая-то более серьезная работа, или по заданию требуется, чтобы это был класс - то лучше такие мелкие однострочные функции делать inline (встраиваемыми), т.е. определять их прямо в объявлении класса. Это позволит компилятору не вызывать их, а просто встраивать в код, что благотворно сказывается на производительности. И еще - я бы делал все функции возврата константными - чтобы их можно было вызывать и для константных объектов. Строки я бы передавал как константные ссылки, чтобы поменьше копировать.

class Student{
  public:
    Student();
    void   setName(const string& s)    { name = s; }
    string getName() const             { return name; }
    void   setSurname(const string& s) { surname = s; }
    string getSurname() const          { return surname; }
    ...
  private:
    string name;
    string surname;
    int age;
    int course;
    string group;
    string* marks;
};

Еще - оценки у вас явно односимвольные, так что я бы не городил массив строк, а использовал просто строку - которая, в общем-то, и есть массив символов (при этом я бы дописал функцию добавления оценки - т.е. присоединения к этой строке очередного символа). Кроме того, вы бы избавились и от того, что именуют "волшебными константами" - вам не надо было бы при выводе помнить, что оценок 6:

for(char c : mark){
    cout << c <<" ";
}

И еще - все строки вы в класс копируете, что правильно - объект получается самодостаточен, "все свое ношу с собой". А вот этот массив вы просто передаете как указатель на внешнюю по отношению к классу сущность. и если поменяется она - поменяется, получается, и состояние класса. Грубо говоря, зачетка вашего студента - не зачетка, а обложка с бумажкой, на которой написано - "а оценки мои записаны вон там, на классной доске" - где их сможет подправить любой хулиган... Т.е. если даже вы работаете с массивом строк - его лучше скопировать внутрь, для пущей инкапсуляции.

И еще - почему бы вам не создать еще один конструктор, который бы создавал сразу именованного студента? Вряд ли имя и фамилия будут меняться (разве что студентка замуж выйдет :)).

READ ALSO
Можно-ли изменить данные в массиве VAO?

Можно-ли изменить данные в массиве VAO?

ЗдравствуйтеОбращаюсь к специалистам OpenGL

272
undefined reference to operator&lt;&lt; [дубликат]

undefined reference to operator<< [дубликат]

На данный вопрос уже ответили:

261
Несколько мод числового ряда c++

Несколько мод числового ряда c++

Делаю задания по книге Бьярне Страуструпа "Программирование: принципы и практика с использованием C++, 2-е издание"Во главе 4, задании 16 надо...

283
MinGW или Cygwin?

MinGW или Cygwin?

Раньше просто компилировал с помощью g++ на Ubuntu, вытягивая компилятор с помощью пакетного менеджера:

357