Class lenght работа с enum

Прошу помочь разобраться с классом «Длина». Не пойму, как работать с enum в классе.
это величины длин по отношению к метру

Как сделать чтобы величины в enum einheit {DM,M,KM,FT,YD,MI} приняли тип дабл? через функцию? и не получается создать конструктор копирования с enum.

enum einheit {DM,M,KM,FT,YD,MI};  
int main() {  
 Laenge a; //1 m 
 Laenge b(50); //50 m   
Laenge c(17, YD); //17 Yard   

Вывод:

 1m, 50m, 17yd 

Я попыталась что то придумать, но мне компилятор выдает лишь числа (1 1, 50 1,17 1). Почему 1? так потому что я указала метр=1.

это файл Laenge.cpp

#include"Laenge.h"
namespace Programm {
    Laenge::Laenge()
    {
        metr = 1;
        einheit c = (einheit)M;
    }

    Laenge::Laenge(double m, einheit n)
    {
        metr = m;
        einheit n;
    }

     double einh(char n) // не работает. Поначалу это было в конструкторе                            
                                            //(Laenge::Laenge(double m, einheit n).
    {   
        einheit n;
        switch (n)
        {
        case DM: cout << "DM"; break;
        case KM: cout << "KM"; break;
        case FT: cout << "FT"; break;
        case YD: cout << "YD"; break;
        case MI: cout << "MI"; break;
        default: cout << "M"; break;
        }
    }

    std::ostream& operator<<(std::ostream& os, Laenge l)
    {
        return os << l.metr << " " << //(einheit)l не пойму как указывать;
    }

    Laenge::~Laenge()
    {
    }

Спасибо!

rrg01, а где файл Laenge.h? Как-то сложно догадаться что там написано ((
И main.cpp тоже хотелось бы целиком посмотреть.

(1) Член перечисления, конечно можно преобразовать в double, но это извращение. По стандарту члены перечисления должны иметь интегральный тип (т.е. какой-то из целых типов: int, long, unsigned и т.п.).

(2) Конструктора копирования я в коде вообще не вижу.

(3) Формальный текст задания можно посмотреть? Не совсем понятно что ты пытаешься сделать.

(4) Нормально оформить исходный код в посте у тебя опять не получилось (( Читай ещё раз:

... производите оформление кода вручную, следующим образом:

```cpp

исходный код

```

Три символа перед cpp (cpp — это пометка языка, можно не указывать) — это обратные апострофы. На клавиатуре этот символ обычно располагается на той же кнопке, что и тильда (~).

Вот main(), где естественно, менять ничего нельзя.


#include <iostream>
#include "Laenge.h"
using namespace std;
using Programm::Laenge;

enum einheit {DM,M,KM,FT,YD,MI}; 

int main() { 
 Laenge a; //1 m   
Laenge b(50); //50 m   
Laenge c(17, YD); //17 Yard   
try 
{     
Laenge d(-5); //-5 m   
}   catch (...) {     cout << "Отрицательная длина!" << endl;   }  

cout << a << ", " << b << " = " << b.umrechnen(DM) << "dm, " << c << endl;  
//b.umrechnen(DM) -> функция, которая будет конвертировать величины, этого я пока не ////делала, так как сперва хочу понять работу с enum.
try 
{     
cout << b+a-c << endl;     
cout << b-2*Laenge(1,YD)*0.25 << endl;     
cout << a-c << endl;   
}   
catch (...) {     cout << "Отрицательная длина!" << endl;   }  
try 
{     
a = (Laenge(10,MI)*0.5-2*(Laenge(2,KM)+Laenge(17,YD))); // оператор умножения на цифру,                  //и цифру на Laenge;это я тоже пока что оставила. 
a.konvertieren(M);     
cout << a << endl;   
a = a*(-2);  
}   
catch (...) {     cout << "Отрицательная длина!" << endl;   }  

Laenge arr[] = {Laenge(1,DM), Laenge(1,FT), Laenge(1,YD)};  
Laenge::minimum(arr,3) = Laenge(1,MI);  // static Laenge& minimum(Laenge[], int);
Laenge::minimum(arr,3) = Laenge(1);   
for (int i=0; i<3; ++i)     
cout << arr[i] << endl;  
  return 0; 
}

Вывод:
Отрицательная длина!
1m, 50m = 500dm, 17yd 
35.4552m 
49.5428m 
Отрицательная длина!
4015.61m 
Отрицательная длина!
1mi 
1m 
1yd  


**Laenge.h**

#pragma once
#include <iostream>
using namespace std;
namespace Programm {
    class Laenge
    {
        double metr;
        enum einheit { DM, M, KM, FT, YD, MI };

    public:
        Laenge();
        Laenge(double, einheit);
        Laenge(const Laenge& l);
        Laenge (Laenge& l);

        friend std::ostream& operator<<(std::ostream& os, Laenge& l);


        ~Laenge();
    };
}
**Laenge.cpp**

#include "Laenge.h"
namespace Programm {

    Laenge::Laenge()
    {
        metr = 1;
        einheit c = (einheit)M;
    }

    Laenge::Laenge(const Laenge& l)
    {
        metr = l.metr;
        einheit l;
    }

    Laenge::Laenge(double m, einheit n)
    {
        metr = m;
        einheit n;
        switch (n)
        {
        case DM: cout << "DM"; break;
        case KM: cout << "KM"; break;
        case FT: cout << "FT"; break;
        case YD: cout << "YD"; break;
        case MI: cout << "MI"; break;
        default: cout << "M"; break;
        }
    }

    std::ostream& operator<<(std::ostream& os, Laenge& l)
    {
        return os << l.metr << " " << (einheit)l;
    }

    Laenge::~Laenge()
    {
    }
} 

Спасибо за подсказку оформления!
Набирала все вручную, не могла понять что не так) Теперь все ясно

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

(1) Дублирование определения enum einheit {DM,M,KM,FT,YD,MI} в main.cpp и классе Laenge. Причём первое доступно глобально, но только в main.cpp. А второе доступно только внутри класса Laenge, поскольку описано как private (неявно). Решение: в Laenge.h вынести в глобальную область видимости, в main.cpp убрать определение и прописать using Programm::einheit.

(2) Класс должен быть описан так:

    enum einheit { DM, M, KM, FT, YD, MI };  // здесь определяется новый тип

    class Laenge
    {
        double metr;
        einheit unit;  // тип переменной einheit

    public:
        Laenge();
        Laenge(double, einheit);
        Laenge(const Laenge& l);

        // ...остальные методы...

        friend std::ostream& operator<<(std::ostream& os, Laenge& l);
        friend Laenge operator + (const Laenge& lho, const Laenge& rho);
        // ...остальные операторы...

        // деструктор для этого класса вообще не нужен
    };

(3) Конструктор копии:

    Laenge::Laenge(const Laenge& l)
    {
        metr = l.metr;
        unit = l.unit;
    }

Остальные — сама додумаешь.

(4) Из конструктора Laenge::Laenge(double m, einheit n) убрать switch.

(5) Оператор std::ostream& operator<<(std::ostream& os, Laenge& l) сделать так:

    const char **unit_labels = { "dm", "m", "km", "ft", "yd", "mi" };

    std::ostream& operator<<(std::ostream& os, const Laenge& l)
    {
        return os << l.metr << unit_labels[(int)l.unit];
    }

Коротко: Считай, что тип-перечисление (enum) — это ограниченный набор именованных целых констант. Первая константа в наборе (по умолчанию) имеет значение 0. Каждая следующая константа (по умолчанию) имеет значение на 1 больше предыдущей. Переменные типа-перечисления можно сравнивать и приводить к числовому типу.

Попробуй сделать то, что я написал. Исходники и вопросы выкладывай — посмотрим что получилось.

Про enum я уже многое прочла, и использовать вне класса могу. Но в данном случае, не совсем понимаю.
К сожалению не разрешается по заданию использовать глобальные переменные.
Я все же попробовала по вашему методу усовершенствовать прг. Но к сожалению он выдает ошибку.
далее я изменила её так вот:


**Laenge.cpp**

#include "Laenge.h"
namespace Programm {

    Laenge::Laenge()
    {
        metr=1;
        einheit c = (einheit)M;
    }

    Laenge::Laenge(int m, einheit n)
    {
        metr = m;
        unit = n;
    }

    Laenge::Laenge(const Laenge& l)
    {
        metr = l.metr;
        unit = l.unit;
    }

    //const char **unit_labels = { "DM", "M", "KM", "FT", "YD", "MI"};
    std::ostream& operator<<(std::ostream& os, const Laenge& l)
    {
        os << l.metr << " ";
        switch (l.unit)
        {
        case 0: os << "DM"; break;
        case 2: os << "KM"; break;
        case 3: os << "FT"; break;
        case 4: os << "YD"; break;
        case 5: os << "MI"; break;
        default: os << "M"; break;
        }
        os << l.unit;
        return os;
    }

}
**Laenge.h**

#pragma once
#include <iostream>
using namespace std;
namespace Programm {

    class Laenge
    {       
    public:
        enum einheit { DM, M, KM, FT, YD, MI };
        Laenge();
        Laenge(int, einheit);
        Laenge (const Laenge& l);

        friend std::ostream& operator<<(std::ostream& os, const Laenge& l);

    private:
        int metr;
        einheit unit;
    };
}

Но он выдает такую вот Ошибку:
Ошибкa C2664 «Programm::Laenge::Laenge(const Programm::Laenge &)»: невозможно преобразовать аргумент 2 из «einheit» в «Programm::Laenge::einheit» class_laenge

И как я понимаю ошибка здесь:
Laenge::Laenge(int m, einheit n)
{
metr = m;
unit = n; // Ошибка. но почему?
}

(1) См. п.1 предыдущего поста.

Дублирование определения enum einheit {DM,M,KM,FT,YD,MI} ... Решение: в Laenge.h вынести в глобальную область видимости, в main.cpp убрать определение и прописать using Programm::einheit.

На этом ты ошибку и словила. Потому что у тебя в программе одновременно существуют ::einheit (глобальный) и Programm::Laenge::einheit (определённый в классе). Так не надо делать.

Возвращаясь к моему совету. Есть одна тонкость. Если einheitопределить в Laenge.h в глобальном пространстве имён, то проблем нет. Если einheit определить в Laenge.h в пространстве имён Programm, то в main.cpp придётся либо импортировать все члены перечисления по отдельности

using Programm::DM;
using Programm::M;
using Programm::KM;
using Programm::FT;
using Programm::YD;
using Programm::MI;

либо квалифицировать каждую константу при использовании пространством имён например

Laenge c(17, Programm::YD); //17 Yard

либо подтягивать в main.cpp всё пространство имён Programm

using namespace Programm;

Подтянуть имена констант, подтянув название типа перечисления, как я написал раньше, не получится. Стандарт ISO/IEC 14882:2011 п.7.3.3.1:

[Note: Only the specified name is so declared; specifying an enumeration name in a
using-declaration does not declare its enumerators in the using-declaration’s declarative region. —end note]

(2) Если main.cpp изменять нельзя от слова «совсем», то формулировка задания некорректна. Определение einheit должно быть (а) либо в Laenge.h, (б) либо в отдельном заголовочном файле, который включается и в main.cpp, и в Laenge.h, (в) либо Laenge.h вместе с Laenge.cpp должны быть в main.cpp (одним файлом).

(3) Кстати ещё по поводу корректности задания. Интересный момент:

cout << b+a-c << endl;     // вывод: 35.4552m

a и b заданы в метрах, c — в ярдах. Почему результат получается в метрах, а не в ярдах? А если написать c + c, то результат тоже будет в метрах?

Или ещё:

        a = (Laenge(10, MI)*0.5 - 2 * (Laenge(2, KM) + Laenge(17, YD)));
        a.konvertieren(M);

Метод «конвертирен», на сколько я понимаю, должен сконвертировать переменную a в метры. Хорошо. А в результате выполнения предыдущей строки, для a какие единицы будут установлены?

(4) Глобальные переменные я не предлагал использовать. Определение перечисления — это определение нового типа данных, такое же, как определение класса или структуры.

(5) После тупого разглядывания main(), у меня появилась мысль, что в класс Laenge неплохо бы добавить ещё один член:

    private:
        double metr;        // длина МЕТРАХ
        double len;         // длина в единицах, указанных в unit
        einheit unit;       // единицы длины

Все вычисления проводить в метрах, а вывод показывать в тех единицах, которые заданы. Мне кажется так удобнее, чем держать матрицу коэффициентов для пересчёта одних единиц в другие.

(6) Кстати, длину нужно хранить таки в double, а не в int. А то так переведешь футы в метры и обратно... ))

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.