C++ Создать экземпляр класса, используя заданный размер динамической памяти

146
18 сентября 2019, 02:10

Нужно создать экземпляр класса, используя заданный размер динамической памяти. Пробовал прописать вот так Stroka *stroka = new Stroka[10];, но появляется сообщение "выражение должно иметь тип класса".

Ошибка C2228 выражение слева от ".vvod" должно представлять класс, структуру или объединение

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

~Stroka() // деструктор
{
    delete[] str;
};

Код программы ниже:

#include "pch.h"
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <malloc.h>
using namespace std;
class Stroka {
    char str[80];
public:
    Stroka(char*); //конструктор с параметром, ссылка на объект не фиксированного размера
    Stroka(const char*); //конструктор с параметром, ссылка на объект фиксированного размера
    Stroka() {}; //конструктор без параметров
    Stroka(const Stroka&); // Конструктор копирования
    void vvod();
    void vyvod();
}
;
Stroka::Stroka(char *string)
{
    strcpy(str, string);
}
Stroka::Stroka(const Stroka& s)
{
    strcpy(str, s.str);
}
void Stroka::vvod()
{
    cout << "Введите текст:" << endl;
    cin >> str;
}
void Stroka::vyvod()
{
    cout << "Вывод текста на экран:" << endl;
    cout << str << endl;
}
int main(int)
{
    setlocale(0, ""); // установить русскую локацию
    Stroka *s1 = new Stroka[80];
    //Stroka s1;
    s1.vvod();
    s1.vyvod();
}
;
Answer 1

s1 объявлен как указатель, из-за чего для доступа к полю объекта надо использовать не точку, а стрелку:

s1->vvod();
s1->vyvod();

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

Компилятор потому и требует «класс, структуру или объединение», что только в них могут быть объявлены поля и методы. Сам же указатель слишком примитивен для этого. И сразу же отвечу на потенциальный вопрос: «почему нельзя везде использовать точку, если указатель в принципе не имеет своих полей»: есть ещё умные указатели, являющиеся полноценными классами и имеющие-таки собственные методы помимо указываемого объекта.

Answer 2

Выделяем динамическую память:

void * mem = operator new (sizeof(Stroka));

Для удобства делаем ссылку на нужный тип:

Stroka & str = (* ((Stroka *) mem ));

Вызываем конструктор объекта на этом месте:

new(mem) Stroka();

Потом НЕ забываем вызвать деструктор:

str.~Stroka();

И НЕ забываем освобождать память:

operator delete ( mem ) ;

Ваш деструктор НЕ нужен, так как массив str[80] - удаляется вместе с объектом.

~Stroka() // деструктор
{
    // delete[] str; не надо
};
Answer 3

@HolyBlackCat Всё забываю синтаксис - мракобесие етот new. Я пытаюсь догадаться условие задачи и прикинул так. Наверное нужно уточнить, что надо?

Нужно сделать вариант конструктора, который создает экземпляр класса, используя заданный размер динамической памяти. я только изучаю язык, предположил, что в самом простом варианте это как то делается через new (для меня это просто привычный синтаксис, хотя я прочитал, что в C++ это дурной тон).

Не могу понять как использовать ваш совет. Не могли бы вы выложить внутри моего примера, так было бы в разы понятнее.

У меня получилось вот так:

int main(int)
{
    setlocale(0, ""); // установить русскую локацию
    Stroka *s1;
    s1 = new Stroka;
    //Stroka s1;
    s1->vvod();
    s1->vyvod();
    delete s1;
}
READ ALSO
Насколько сейчас актуально WinAPI? [закрыт]

Насколько сейчас актуально WinAPI? [закрыт]

Изучаю разработку программ на C++ по книгамТам для создания окон и многого другого используется библиотека WinAPI

129
Присоеденение boost к CMake

Присоеденение boost к CMake

FIND_PACKAGE(Boost) - ищет boost по стандартному пути /usr/local/, мой boost лежит по пути /home/cheshirecat/libs Как сделать так, чтобы FIND_PACKAGE(Boost) нашел boost?

117
Разные результаты base64

Разные результаты base64

Всех приветствуюПытаюсь на python расшифровать сообщения C++'a

107