C ++ Конструкторы и классы? - PullRequest
0 голосов
/ 10 января 2020

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

Код предназначен для того, чтобы я мог ввести числовую оценку и букву, например, 100 F. И взамен он должен сказать мне буквенную оценку для первого значения и числовое значение для буквы: 100: А и 45: F. Я уверен, что функции являются правильными, и я главное имеет смысл. Ошибка, которую я получаю, говорит, что для класса g нет соответствующей функции; в моей главной.

class Grade {

public:

    int* percent;
    char* letter;
    char GRADE_MAP [11] = {'F', 'F', 'F', 'F', 'F', 'F', 'D', 'C', 'B', 'A', 'A'};

    Grade(int p, char l){
        percent = new int;
        letter = new char;
        *percent = p;
        *letter = l;
    }

    ~Grade(){
        delete percent;
        delete letter;
    }

    void setByPercent(int p){
        p = *percent;
        *letter = GRADE_MAP[p / 10];
    }

    void setByLetter(char l){
        l = *letter;
        *percent = 100 - (l - 'A') * 10 - 5;
    }

    void print(){
        printf("Grade: %d: %c \n", *percent, *letter);
    }
};


int main() {

    int percent;
    Grade g;

    printf("Enter two grades separated by a space. Use a percentage for the first and letter for the second: \n");

    scanf("%d", &percent);
    scanf("\n");

    g.setByPercent(percent);
    g.print();

    g.setByLetter(getchar());
    g.print();

    return 0;
}

Ответы [ 2 ]

2 голосов
/ 10 января 2020

Ладно, обо всем по порядку: вы совершенно неправильно используете динамическую c память. Нет смысла динамически выделять single int или один символ. Указатель по крайней мере имеет размер int, если не вдвое больше (в зависимости от комбинации процессора и ОС), а для символа он в 4 или 8 раз больше. Плюс косвенная стоимость.

Кроме того, определив GRADE_MAP как обычный инициализированный член класса, вы создаете его копию для каждого экземпляра.

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

Так что давайте избавимся от этого.

Сначала включите iostream и sstream для вывода

 #include <sstream>
 #include <iostream>

 class Grade {

просто обычный член, без динамических элементов c

     int  percent;
     char letter;

делает это static и const для перемещения этого в исполняемые файлы .rodata section

    static char const GRADE_MAP [11] = {'F', 'F', 'F', 'F', 'F', 'F', 'D', 'C', 'B', 'A', 'A'};

Stati c вспомогательные функции для преобразования, используемые сеттерами и конструкторами:

    static int fromLetter(char l){
        int p = 100 - (l - 'A') * 10 - 5;
        if( 0 > p || 100 < p ){
            throw std::range_error("equivalent percentage out of range");
        }
        return p;
    }
    static char fromPercent(int p){
        if( 0 > p || 100 < p ){
            throw std::range_error("percentage out of range");
        }
        return GRADE_MAP[p / 10];
    }

Конструктор должен быть опубликован c

public:

Используйте здесь инициализаторы

     Grade(int p)
     : percent(p)
     , letter( fromPercent(p) )
     {}

     Grade(char l)
     : percent( fromLetter(l) )
     , letter( l )
     {}


     ~Grade(){}

Вы, вероятно, хотели получить процент от p. То, как вы это написали, игнорирует параметр

    void setByPercent(int p){
         percent = p;
         letter = fromPercentage(p);
    }

    void setByLetter(char l){
         letter = l;
         percent = fromLetter(l);
    }

Наконец, будьте C ++ -i sh и используйте iostream

     basic_ostringstream strstr(){
         basic_ostringstream os;
         os << "Grade: " << percent << ": " << letter;
         return os;
     }
};

int main() {

    int percent, letter;
     std::cout << "Enter two grades separated by a space. Use a percentage for the first and letter for the second:" << std::endl;
     std::cin >> percent >> letter;     

     Grade g1(percent)
     Grade g2(letter)

     std::cout << g1.strstr() << "; " << g2.strstr() << std::endl;
    return 0;
}
1 голос
/ 10 января 2020

Для начала эти две функции-члены недопустимы

void setByPercent(int p){
    p = *percent;
    *letter = GRADE_MAP[p / 10];
}

void setByLetter(char l){
    l = *letter;
    *percent = 100 - (l - 'A') * 10 - 5;
}

Кажется, вы имеете в виду

void setByPercent(int p){
    *percent = p;
    *letter = GRADE_MAP[p / 10];
}

и

void setByLetter(char l){
    *letter = l;
    *percent = 100 - (l - 'A') * 10 - 5;
}

Класс не имеет значения по умолчанию конструктор. Так что это объявление

Grade g;

неверно, потому что здесь должен вызываться конструктор по умолчанию, который отсутствует.

Укажите аргументы для созданного объекта, например,

Grade g( 100, 'A' );
...